diff --git a/localized_fields/__init__.py b/localized_fields/__init__.py
index 45ff2ec..93dd4c6 100644
--- a/localized_fields/__init__.py
+++ b/localized_fields/__init__.py
@@ -1 +1 @@
-default_app_config = 'localized_fields.apps.LocalizedFieldsConfig'
+default_app_config = "localized_fields.apps.LocalizedFieldsConfig"
diff --git a/localized_fields/admin.py b/localized_fields/admin.py
index e7af13f..63650e0 100644
--- a/localized_fields/admin.py
+++ b/localized_fields/admin.py
@@ -1,13 +1,16 @@
from . import widgets
-from .fields import LocalizedField, LocalizedCharField, LocalizedTextField, \
- LocalizedFileField
-
+from .fields import (
+ LocalizedCharField,
+ LocalizedField,
+ LocalizedFileField,
+ LocalizedTextField,
+)
FORMFIELD_FOR_LOCALIZED_FIELDS_DEFAULTS = {
- LocalizedField: {'widget': widgets.AdminLocalizedFieldWidget},
- LocalizedCharField: {'widget': widgets.AdminLocalizedCharFieldWidget},
- LocalizedTextField: {'widget': widgets.AdminLocalizedFieldWidget},
- LocalizedFileField: {'widget': widgets.AdminLocalizedFileFieldWidget},
+ LocalizedField: {"widget": widgets.AdminLocalizedFieldWidget},
+ LocalizedCharField: {"widget": widgets.AdminLocalizedCharFieldWidget},
+ LocalizedTextField: {"widget": widgets.AdminLocalizedFieldWidget},
+ LocalizedFileField: {"widget": widgets.AdminLocalizedFileFieldWidget},
}
@@ -15,15 +18,11 @@ class LocalizedFieldsAdminMixin:
"""Mixin for making the fancy widgets work in Django Admin."""
class Media:
- css = {
- 'all': (
- 'localized_fields/localized-fields-admin.css',
- )
- }
+ css = {"all": ("localized_fields/localized-fields-admin.css",)}
js = (
- 'admin/js/jquery.init.js',
- 'localized_fields/localized-fields-admin.js',
+ "admin/js/jquery.init.js",
+ "localized_fields/localized-fields-admin.js",
)
def __init__(self, *args, **kwargs):
diff --git a/localized_fields/apps.py b/localized_fields/apps.py
index 7dec5df..ac62fdb 100644
--- a/localized_fields/apps.py
+++ b/localized_fields/apps.py
@@ -9,10 +9,10 @@ from .lookups import LocalizedLookupMixin
class LocalizedFieldsConfig(AppConfig):
- name = 'localized_fields'
+ name = "localized_fields"
def ready(self):
- if getattr(settings, 'LOCALIZED_FIELDS_EXPERIMENTAL', False):
+ if getattr(settings, "LOCALIZED_FIELDS_EXPERIMENTAL", False):
for _, clazz in inspect.getmembers(lookups):
if not inspect.isclass(clazz) or clazz is LocalizedLookupMixin:
continue
diff --git a/localized_fields/descriptor.py b/localized_fields/descriptor.py
index 4d2babc..8b4f30d 100644
--- a/localized_fields/descriptor.py
+++ b/localized_fields/descriptor.py
@@ -3,8 +3,7 @@ from django.utils import six, translation
class LocalizedValueDescriptor:
- """
- The descriptor for the localized value attribute on the model instance.
+ """The descriptor for the localized value attribute on the model instance.
Returns a :see:LocalizedValue when accessed so you can do stuff like::
>>> from myapp.models import MyModel
@@ -60,6 +59,8 @@ class LocalizedValueDescriptor:
def __set__(self, instance, value):
if isinstance(value, six.string_types):
language = translation.get_language() or settings.LANGUAGE_CODE
- self.__get__(instance).set(language, value) # pylint: disable=no-member
+ self.__get__(instance).set(
+ language, value
+ ) # pylint: disable=no-member
else:
instance.__dict__[self.field.name] = value
diff --git a/localized_fields/expressions.py b/localized_fields/expressions.py
index b0314b2..0b6c041 100644
--- a/localized_fields/expressions.py
+++ b/localized_fields/expressions.py
@@ -1,14 +1,13 @@
from django.conf import settings
from django.utils import translation
-
from psqlextra import expressions
class LocalizedRef(expressions.HStoreRef):
- """Expression that selects the value in a field only in
- the currently active language."""
+ """Expression that selects the value in a field only in the currently
+ active language."""
- def __init__(self, name: str, lang: str=None):
+ def __init__(self, name: str, lang: str = None):
"""Initializes a new instance of :see:LocalizedRef.
Arguments:
diff --git a/localized_fields/fields/__init__.py b/localized_fields/fields/__init__.py
index 3a4c2d7..6bd3580 100644
--- a/localized_fields/fields/__init__.py
+++ b/localized_fields/fields/__init__.py
@@ -1,26 +1,24 @@
-from .field import LocalizedField
from .autoslug_field import LocalizedAutoSlugField
-from .uniqueslug_field import LocalizedUniqueSlugField
from .char_field import LocalizedCharField
-from .text_field import LocalizedTextField
+from .field import LocalizedField
from .file_field import LocalizedFileField
from .integer_field import LocalizedIntegerField
-
+from .text_field import LocalizedTextField
+from .uniqueslug_field import LocalizedUniqueSlugField
__all__ = [
- 'LocalizedField',
- 'LocalizedAutoSlugField',
- 'LocalizedUniqueSlugField',
- 'LocalizedCharField',
- 'LocalizedTextField',
- 'LocalizedFileField',
- 'LocalizedIntegerField'
+ "LocalizedField",
+ "LocalizedAutoSlugField",
+ "LocalizedUniqueSlugField",
+ "LocalizedCharField",
+ "LocalizedTextField",
+ "LocalizedFileField",
+ "LocalizedIntegerField",
]
try:
from .bleach_field import LocalizedBleachField
- __all__ += [
- 'LocalizedBleachField'
- ]
+
+ __all__ += ["LocalizedBleachField"]
except ImportError:
pass
diff --git a/localized_fields/fields/autoslug_field.py b/localized_fields/fields/autoslug_field.py
index e3ee261..28cf037 100644
--- a/localized_fields/fields/autoslug_field.py
+++ b/localized_fields/fields/autoslug_field.py
@@ -1,60 +1,53 @@
import warnings
-from typing import Callable, Tuple, Union
from datetime import datetime
+from typing import Callable, Tuple, Union
from django import forms
from django.conf import settings
from django.utils import translation
from django.utils.text import slugify
-from .field import LocalizedField
-from ..value import LocalizedValue
from ..util import resolve_object_property
+from ..value import LocalizedValue
+from .field import LocalizedField
class LocalizedAutoSlugField(LocalizedField):
- """Automatically provides slugs for a localized
- field upon saving."""
+ """Automatically provides slugs for a localized field upon saving."""
warnings.warn(
- 'LocalizedAutoSlug is deprecated and will be removed in the next major version.',
- DeprecationWarning
+ "LocalizedAutoSlug is deprecated and will be removed in the next major version.",
+ DeprecationWarning,
)
def __init__(self, *args, **kwargs):
"""Initializes a new instance of :see:LocalizedAutoSlugField."""
- self.populate_from = kwargs.pop('populate_from', None)
- self.include_time = kwargs.pop('include_time', False)
+ self.populate_from = kwargs.pop("populate_from", None)
+ self.include_time = kwargs.pop("include_time", False)
- super(LocalizedAutoSlugField, self).__init__(
- *args,
- **kwargs
- )
+ super(LocalizedAutoSlugField, self).__init__(*args, **kwargs)
def deconstruct(self):
- """Deconstructs the field into something the database
- can store."""
+ """Deconstructs the field into something the database can store."""
name, path, args, kwargs = super(
- LocalizedAutoSlugField, self).deconstruct()
+ LocalizedAutoSlugField, self
+ ).deconstruct()
- kwargs['populate_from'] = self.populate_from
- kwargs['include_time'] = self.include_time
+ kwargs["populate_from"] = self.populate_from
+ kwargs["include_time"] = self.include_time
return name, path, args, kwargs
def formfield(self, **kwargs):
"""Gets the form field associated with this field.
- Because this is a slug field which is automatically
- populated, it should be hidden from the form.
+ Because this is a slug field which is automatically populated,
+ it should be hidden from the form.
"""
- defaults = {
- 'form_class': forms.CharField,
- 'required': False
- }
+ defaults = {"form_class": forms.CharField, "required": False}
defaults.update(kwargs)
@@ -64,8 +57,7 @@ class LocalizedAutoSlugField(LocalizedField):
return form_field
def pre_save(self, instance, add: bool):
- """Ran just before the model is saved, allows us to built
- the slug.
+ """Ran just before the model is saved, allows us to built the slug.
Arguments:
instance:
@@ -83,21 +75,19 @@ class LocalizedAutoSlugField(LocalizedField):
continue
if self.include_time:
- value += '-%s' % datetime.now().microsecond
+ value += "-%s" % datetime.now().microsecond
def is_unique(slug: str, language: str) -> bool:
"""Gets whether the specified slug is unique."""
- unique_filter = {
- '%s__%s' % (self.name, language): slug
- }
+ unique_filter = {"%s__%s" % (self.name, language): slug}
- return not type(instance).objects.filter(**unique_filter).exists()
+ return (
+ not type(instance).objects.filter(**unique_filter).exists()
+ )
slug = self._make_unique_slug(
- slugify(value, allow_unicode=True),
- lang_code,
- is_unique
+ slugify(value, allow_unicode=True), lang_code, is_unique
)
slugs.set(lang_code, slug)
@@ -106,9 +96,11 @@ class LocalizedAutoSlugField(LocalizedField):
return slugs
@staticmethod
- def _make_unique_slug(slug: str, language: str, is_unique: Callable[[str], bool]) -> str:
- """Guarentees that the specified slug is unique by appending
- a number until it is unique.
+ def _make_unique_slug(
+ slug: str, language: str, is_unique: Callable[[str], bool]
+ ) -> str:
+ """Guarentees that the specified slug is unique by appending a number
+ until it is unique.
Arguments:
slug:
@@ -126,14 +118,14 @@ class LocalizedAutoSlugField(LocalizedField):
unique_slug = slug
while not is_unique(unique_slug, language):
- unique_slug = '%s-%d' % (slug, index)
+ unique_slug = "%s-%d" % (slug, index)
index += 1
return unique_slug
def _get_populate_values(self, instance) -> Tuple[str, str]:
- """Gets all values (for each language) from the
- specified's instance's `populate_from` field.
+ """Gets all values (for each language) from the specified's instance's
+ `populate_from` field.
Arguments:
instance:
@@ -147,16 +139,16 @@ class LocalizedAutoSlugField(LocalizedField):
(
lang_code,
self._get_populate_from_value(
- instance,
- self.populate_from,
- lang_code
+ instance, self.populate_from, lang_code
),
)
for lang_code, _ in settings.LANGUAGES
]
@staticmethod
- def _get_populate_from_value(instance, field_name: Union[str, Tuple[str]], language: str):
+ def _get_populate_from_value(
+ instance, field_name: Union[str, Tuple[str]], language: str
+ ):
"""Gets the value to create a slug from in the specified language.
Arguments:
@@ -182,11 +174,13 @@ class LocalizedAutoSlugField(LocalizedField):
return str(value)
if isinstance(field_name, tuple) or isinstance(field_name, list):
- value = '-'.join([
- value
- for value in [get_field_value(name) for name in field_name]
- if value
- ])
+ value = "-".join(
+ [
+ value
+ for value in [get_field_value(name) for name in field_name]
+ if value
+ ]
+ )
return value
return get_field_value(field_name)
diff --git a/localized_fields/fields/bleach_field.py b/localized_fields/fields/bleach_field.py
index 3535de7..121a4a3 100644
--- a/localized_fields/fields/bleach_field.py
+++ b/localized_fields/fields/bleach_field.py
@@ -7,12 +7,11 @@ from .field import LocalizedField
class LocalizedBleachField(LocalizedField):
- """Custom version of :see:BleachField that
- is actually a :see:LocalizedField."""
+ """Custom version of :see:BleachField that is actually a
+ :see:LocalizedField."""
def pre_save(self, instance, add: bool):
- """Ran just before the model is saved, allows us to built
- the slug.
+ """Ran just before the model is saved, allows us to built the slug.
Arguments:
instance:
@@ -33,8 +32,7 @@ class LocalizedBleachField(LocalizedField):
continue
localized_value.set(
- lang_code,
- bleach.clean(value, **get_bleach_default_options())
+ lang_code, bleach.clean(value, **get_bleach_default_options())
)
return localized_value
diff --git a/localized_fields/fields/char_field.py b/localized_fields/fields/char_field.py
index 6799b4f..4a9c91c 100644
--- a/localized_fields/fields/char_field.py
+++ b/localized_fields/fields/char_field.py
@@ -1,6 +1,6 @@
from ..forms import LocalizedCharFieldForm
-from .field import LocalizedField
from ..value import LocalizedStringValue
+from .field import LocalizedField
class LocalizedCharField(LocalizedField):
@@ -8,9 +8,7 @@ class LocalizedCharField(LocalizedField):
def formfield(self, **kwargs):
"""Gets the form field associated with this field."""
- defaults = {
- 'form_class': LocalizedCharFieldForm
- }
+ defaults = {"form_class": LocalizedCharFieldForm}
defaults.update(kwargs)
return super().formfield(**defaults)
diff --git a/localized_fields/fields/field.py b/localized_fields/fields/field.py
index 72db2c8..8395c5c 100644
--- a/localized_fields/fields/field.py
+++ b/localized_fields/fields/field.py
@@ -1,22 +1,22 @@
import json
-from typing import Union, List, Optional
+from typing import List, Optional, Union
from django.conf import settings
from django.db.utils import IntegrityError
-
from psqlextra.fields import HStoreField
+from ..descriptor import LocalizedValueDescriptor
from ..forms import LocalizedFieldForm
from ..value import LocalizedValue
-from ..descriptor import LocalizedValueDescriptor
class LocalizedField(HStoreField):
"""A field that has the same value in multiple languages.
- Internally this is stored as a :see:HStoreField where there
- is a key for every language."""
+ Internally this is stored as a :see:HStoreField where there is a key
+ for every language.
+ """
Meta = None
@@ -27,7 +27,9 @@ class LocalizedField(HStoreField):
# The descriptor to use for accessing the attribute off of the class.
descriptor_class = LocalizedValueDescriptor
- def __init__(self, *args, required: Union[bool, List[str]]=None, **kwargs):
+ def __init__(
+ self, *args, required: Union[bool, List[str]] = None, **kwargs
+ ):
"""Initializes a new instance of :see:LocalizedField."""
super(LocalizedField, self).__init__(*args, required=required, **kwargs)
@@ -54,8 +56,7 @@ class LocalizedField(HStoreField):
@classmethod
def from_db_value(cls, value, *_) -> Optional[LocalizedValue]:
- """Turns the specified database value into its Python
- equivalent.
+ """Turns the specified database value into its Python equivalent.
Arguments:
value:
@@ -68,7 +69,7 @@ class LocalizedField(HStoreField):
"""
if not value:
- if getattr(settings, 'LOCALIZED_FIELDS_EXPERIMENTAL', False):
+ if getattr(settings, "LOCALIZED_FIELDS_EXPERIMENTAL", False):
return None
else:
return cls.attr_class()
@@ -98,8 +99,7 @@ class LocalizedField(HStoreField):
return cls.attr_class(value)
def to_python(self, value: Union[dict, str, None]) -> LocalizedValue:
- """Turns the specified database value into its Python
- equivalent.
+ """Turns the specified database value into its Python equivalent.
Arguments:
value:
@@ -124,8 +124,7 @@ class LocalizedField(HStoreField):
return self.attr_class(deserialized_value)
def get_prep_value(self, value: LocalizedValue) -> dict:
- """Turns the specified value into something the database
- can store.
+ """Turns the specified value into something the database can store.
If an illegal value (non-LocalizedValue instance) is
specified, we'll treat it as an empty :see:LocalizedValue
@@ -161,8 +160,8 @@ class LocalizedField(HStoreField):
)
def clean(self, value, *_):
- """Cleans the specified value into something we
- can store in the database.
+ """Cleans the specified value into something we can store in the
+ database.
For example, when all the language fields are
left empty, and the field is allowed to be null,
@@ -195,7 +194,7 @@ class LocalizedField(HStoreField):
def validate(self, value: LocalizedValue, *_):
"""Validates that the values has been filled in for all required
- languages
+ languages.
Exceptions are raises in order to notify the user
of invalid values.
@@ -212,15 +211,17 @@ class LocalizedField(HStoreField):
lang_val = getattr(value, settings.LANGUAGE_CODE)
if lang_val is None:
- raise IntegrityError('null value in column "%s.%s" violates '
- 'not-null constraint' % (self.name, lang))
+ raise IntegrityError(
+ 'null value in column "%s.%s" violates '
+ "not-null constraint" % (self.name, lang)
+ )
def formfield(self, **kwargs):
"""Gets the form field associated with this field."""
defaults = dict(
form_class=LocalizedFieldForm,
- required=False if self.blank else self.required
+ required=False if self.blank else self.required,
)
defaults.update(kwargs)
return super().formfield(**defaults)
diff --git a/localized_fields/fields/file_field.py b/localized_fields/fields/file_field.py
index e6777a8..67097ed 100644
--- a/localized_fields/fields/file_field.py
+++ b/localized_fields/fields/file_field.py
@@ -1,31 +1,31 @@
-import json
import datetime
+import json
import posixpath
from django.core.files import File
+from django.core.files.storage import default_storage
from django.db.models.fields.files import FieldFile
from django.utils import six
-from django.core.files.storage import default_storage
from django.utils.encoding import force_str, force_text
from localized_fields.fields import LocalizedField
from localized_fields.fields.field import LocalizedValueDescriptor
from localized_fields.value import LocalizedValue
-from ..value import LocalizedFileValue
from ..forms import LocalizedFileFieldForm
+from ..value import LocalizedFileValue
class LocalizedFieldFile(FieldFile):
-
def __init__(self, instance, field, name, lang):
super().__init__(instance, field, name)
self.lang = lang
def save(self, name, content, save=True):
name = self.field.generate_filename(self.instance, name, self.lang)
- self.name = self.storage.save(name, content,
- max_length=self.field.max_length)
+ self.name = self.storage.save(
+ name, content, max_length=self.field.max_length
+ )
self._committed = True
if save:
@@ -37,7 +37,7 @@ class LocalizedFieldFile(FieldFile):
if not self:
return
- if hasattr(self, '_file'):
+ if hasattr(self, "_file"):
self.close()
del self.file
@@ -60,24 +60,29 @@ class LocalizedFileValueDescriptor(LocalizedValueDescriptor):
file = self.field.value_class(instance, self.field, file, lang)
value.set(lang, file)
- elif isinstance(file, File) and \
- not isinstance(file, LocalizedFieldFile):
- file_copy = self.field.value_class(instance, self.field,
- file.name, lang)
+ elif isinstance(file, File) and not isinstance(
+ file, LocalizedFieldFile
+ ):
+ file_copy = self.field.value_class(
+ instance, self.field, file.name, lang
+ )
file_copy.file = file
file_copy._committed = False
value.set(lang, file_copy)
- elif isinstance(file, LocalizedFieldFile) and \
- not hasattr(file, 'field'):
+ elif isinstance(file, LocalizedFieldFile) and not hasattr(
+ file, "field"
+ ):
file.instance = instance
file.field = self.field
file.storage = self.field.storage
file.lang = lang
# Make sure that the instance is correct.
- elif isinstance(file, LocalizedFieldFile) \
- and instance is not file.instance:
+ elif (
+ isinstance(file, LocalizedFieldFile)
+ and instance is not file.instance
+ ):
file.instance = instance
file.lang = lang
return value
@@ -88,8 +93,9 @@ class LocalizedFileField(LocalizedField):
attr_class = LocalizedFileValue
value_class = LocalizedFieldFile
- def __init__(self, verbose_name=None, name=None, upload_to='', storage=None,
- **kwargs):
+ def __init__(
+ self, verbose_name=None, name=None, upload_to="", storage=None, **kwargs
+ ):
self.storage = storage or default_storage
self.upload_to = upload_to
@@ -98,9 +104,9 @@ class LocalizedFileField(LocalizedField):
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
- kwargs['upload_to'] = self.upload_to
+ kwargs["upload_to"] = self.upload_to
if self.storage is not default_storage:
- kwargs['storage'] = self.storage
+ kwargs["storage"] = self.storage
return name, path, args, kwargs
def get_prep_value(self, value):
@@ -110,7 +116,7 @@ class LocalizedFileField(LocalizedField):
prep_value = LocalizedValue()
for k, v in value.__dict__.items():
if v is None:
- prep_value.set(k, '')
+ prep_value.set(k, "")
else:
# Need to convert File objects provided via a form to
# unicode for database insertion
@@ -141,18 +147,17 @@ class LocalizedFileField(LocalizedField):
if isinstance(data, LocalizedValue):
for k, v in data.__dict__.items():
if v is not None and not v:
- data.set(k, '')
+ data.set(k, "")
setattr(instance, self.name, data)
def formfield(self, **kwargs):
- defaults = {'form_class': LocalizedFileFieldForm}
+ defaults = {"form_class": LocalizedFileFieldForm}
defaults.update(kwargs)
return super().formfield(**defaults)
def value_to_string(self, obj):
value = self.value_from_object(obj)
if isinstance(value, LocalizedFileValue):
- return json.dumps({k: v.name for k, v
- in value.__dict__.items()})
+ return json.dumps({k: v.name for k, v in value.__dict__.items()})
else:
return super().value_to_string(obj)
diff --git a/localized_fields/fields/integer_field.py b/localized_fields/fields/integer_field.py
index 6374aa1..745c2c6 100644
--- a/localized_fields/fields/integer_field.py
+++ b/localized_fields/fields/integer_field.py
@@ -1,11 +1,11 @@
-from typing import Optional, Union, Dict
+from typing import Dict, Optional, Union
from django.conf import settings
from django.db.utils import IntegrityError
-from .field import LocalizedField
-from ..value import LocalizedValue, LocalizedIntegerValue
from ..forms import LocalizedIntegerFieldForm
+from ..value import LocalizedIntegerValue, LocalizedValue
+from .field import LocalizedField
class LocalizedIntegerField(LocalizedField):
@@ -27,7 +27,9 @@ class LocalizedIntegerField(LocalizedField):
return cls._convert_localized_value(db_value)
- def to_python(self, value: Union[Dict[str, int], int, None]) -> LocalizedIntegerValue:
+ def to_python(
+ self, value: Union[Dict[str, int], int, None]
+ ) -> LocalizedIntegerValue:
"""Converts the value from a database value into a Python value."""
db_value = super().to_python(value)
@@ -55,32 +57,36 @@ class LocalizedIntegerField(LocalizedField):
if local_value is not None:
int(local_value)
except (TypeError, ValueError):
- raise IntegrityError('non-integer value in column "%s.%s" violates '
- 'integer constraint' % (self.name, lang_code))
+ raise IntegrityError(
+ 'non-integer value in column "%s.%s" violates '
+ "integer constraint" % (self.name, lang_code)
+ )
# convert to a string before saving because the underlying
# type is hstore, which only accept strings
- prepped_value[lang_code] = str(local_value) if local_value is not None else None
+ prepped_value[lang_code] = (
+ str(local_value) if local_value is not None else None
+ )
return prepped_value
def formfield(self, **kwargs):
"""Gets the form field associated with this field."""
- defaults = {
- 'form_class': LocalizedIntegerFieldForm
- }
+ defaults = {"form_class": LocalizedIntegerFieldForm}
defaults.update(kwargs)
return super().formfield(**defaults)
@staticmethod
- def _convert_localized_value(value: LocalizedValue) -> LocalizedIntegerValue:
+ def _convert_localized_value(
+ value: LocalizedValue
+ ) -> LocalizedIntegerValue:
"""Converts from :see:LocalizedValue to :see:LocalizedIntegerValue."""
integer_values = {}
for lang_code, _ in settings.LANGUAGES:
local_value = value.get(lang_code, None)
- if local_value is None or local_value.strip() == '':
+ if local_value is None or local_value.strip() == "":
local_value = None
try:
diff --git a/localized_fields/fields/text_field.py b/localized_fields/fields/text_field.py
index 72dd984..27bac0e 100644
--- a/localized_fields/fields/text_field.py
+++ b/localized_fields/fields/text_field.py
@@ -6,9 +6,7 @@ class LocalizedTextField(LocalizedCharField):
def formfield(self, **kwargs):
"""Gets the form field associated with this field."""
- defaults = {
- 'form_class': LocalizedTextFieldForm
- }
+ defaults = {"form_class": LocalizedTextFieldForm}
defaults.update(kwargs)
return super().formfield(**defaults)
diff --git a/localized_fields/fields/uniqueslug_field.py b/localized_fields/fields/uniqueslug_field.py
index ecfbafd..23e3fdb 100644
--- a/localized_fields/fields/uniqueslug_field.py
+++ b/localized_fields/fields/uniqueslug_field.py
@@ -1,17 +1,16 @@
from datetime import datetime
-from django.utils.text import slugify
from django.core.exceptions import ImproperlyConfigured
+from django.utils.text import slugify
-from .autoslug_field import LocalizedAutoSlugField
-from ..util import get_language_codes
from ..mixins import AtomicSlugRetryMixin
+from ..util import get_language_codes
from ..value import LocalizedValue
+from .autoslug_field import LocalizedAutoSlugField
class LocalizedUniqueSlugField(LocalizedAutoSlugField):
- """Automatically provides slugs for a localized
- field upon saving."
+ """Automatically provides slugs for a localized field upon saving.".
An improved version of :see:LocalizedAutoSlugField,
which adds:
@@ -27,30 +26,26 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
def __init__(self, *args, **kwargs):
"""Initializes a new instance of :see:LocalizedUniqueSlugField."""
- kwargs['uniqueness'] = kwargs.pop('uniqueness', get_language_codes())
+ kwargs["uniqueness"] = kwargs.pop("uniqueness", get_language_codes())
- super(LocalizedUniqueSlugField, self).__init__(
- *args,
- **kwargs
- )
+ super(LocalizedUniqueSlugField, self).__init__(*args, **kwargs)
- self.populate_from = kwargs.pop('populate_from')
- self.include_time = kwargs.pop('include_time', False)
+ self.populate_from = kwargs.pop("populate_from")
+ self.include_time = kwargs.pop("include_time", False)
def deconstruct(self):
- """Deconstructs the field into something the database
- can store."""
+ """Deconstructs the field into something the database can store."""
name, path, args, kwargs = super(
- LocalizedUniqueSlugField, self).deconstruct()
+ LocalizedUniqueSlugField, self
+ ).deconstruct()
- kwargs['populate_from'] = self.populate_from
- kwargs['include_time'] = self.include_time
+ kwargs["populate_from"] = self.populate_from
+ kwargs["include_time"] = self.include_time
return name, path, args, kwargs
def pre_save(self, instance, add: bool):
- """Ran just before the model is saved, allows us to built
- the slug.
+ """Ran just before the model is saved, allows us to built the slug.
Arguments:
instance:
@@ -65,10 +60,13 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
"""
if not isinstance(instance, AtomicSlugRetryMixin):
- raise ImproperlyConfigured((
- 'Model \'%s\' does not inherit from AtomicSlugRetryMixin. '
- 'Without this, the LocalizedUniqueSlugField will not work.'
- ) % type(instance).__name__)
+ raise ImproperlyConfigured(
+ (
+ "Model '%s' does not inherit from AtomicSlugRetryMixin. "
+ "Without this, the LocalizedUniqueSlugField will not work."
+ )
+ % type(instance).__name__
+ )
slugs = LocalizedValue()
@@ -83,20 +81,21 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
if instance.pk is not None:
current_slug = getattr(instance, self.name).get(lang_code)
if current_slug is not None:
- stripped_slug = current_slug[0:current_slug.rfind('-')]
+ current_slug_end_index = current_slug.rfind("-")
+ stripped_slug = current_slug[0:current_slug_end_index]
if slug == stripped_slug:
slugs.set(lang_code, current_slug)
continue
if self.include_time:
- slug += '-%d' % datetime.now().microsecond
+ slug += "-%d" % datetime.now().microsecond
- retries = getattr(instance, 'retries', 0)
+ retries = getattr(instance, "retries", 0)
if retries > 0:
# do not add another - if we already added time
if not self.include_time:
- slug += '-'
- slug += '%d' % retries
+ slug += "-"
+ slug += "%d" % retries
slugs.set(lang_code, slug)
diff --git a/localized_fields/forms.py b/localized_fields/forms.py
index 1077591..19415ab 100644
--- a/localized_fields/forms.py
+++ b/localized_fields/forms.py
@@ -5,30 +5,41 @@ from django.conf import settings
from django.core.exceptions import ValidationError
from django.forms.widgets import FILE_INPUT_CONTRADICTION
-from .value import LocalizedValue, LocalizedStringValue, \
- LocalizedFileValue, LocalizedIntegerValue
-from .widgets import LocalizedFieldWidget, LocalizedCharFieldWidget, \
- LocalizedFileWidget, AdminLocalizedIntegerFieldWidget
+from .value import (
+ LocalizedFileValue,
+ LocalizedIntegerValue,
+ LocalizedStringValue,
+ LocalizedValue,
+)
+from .widgets import (
+ AdminLocalizedIntegerFieldWidget,
+ LocalizedCharFieldWidget,
+ LocalizedFieldWidget,
+ LocalizedFileWidget,
+)
class LocalizedFieldForm(forms.MultiValueField):
- """Form for a localized field, allows editing
- the field in multiple languages."""
+ """Form for a localized field, allows editing the field in multiple
+ languages."""
widget = LocalizedFieldWidget
field_class = forms.fields.CharField
value_class = LocalizedValue
- def __init__(self, *args, required: Union[bool, List[str]]=False, **kwargs):
+ def __init__(
+ self, *args, required: Union[bool, List[str]] = False, **kwargs
+ ):
"""Initializes a new instance of :see:LocalizedFieldForm."""
fields = []
for lang_code, _ in settings.LANGUAGES:
field_options = dict(
- required=required if type(required) is bool else (lang_code in
- required),
- label=lang_code
+ required=required
+ if type(required) is bool
+ else (lang_code in required),
+ label=lang_code,
)
fields.append(self.field_class(**field_options))
@@ -36,7 +47,8 @@ class LocalizedFieldForm(forms.MultiValueField):
fields,
required=required if type(required) is bool else True,
require_all_fields=False,
- *args, **kwargs
+ *args,
+ **kwargs
)
# set 'required' attribute for each widget separately
@@ -44,8 +56,8 @@ class LocalizedFieldForm(forms.MultiValueField):
widget.is_required = field.required
def compress(self, value: List[str]) -> value_class:
- """Compresses the values from individual fields
- into a single :see:LocalizedValue instance.
+ """Compresses the values from individual fields into a single
+ :see:LocalizedValue instance.
Arguments:
value:
@@ -65,41 +77,41 @@ class LocalizedFieldForm(forms.MultiValueField):
class LocalizedCharFieldForm(LocalizedFieldForm):
- """Form for a localized char field, allows editing
- the field in multiple languages."""
+ """Form for a localized char field, allows editing the field in multiple
+ languages."""
widget = LocalizedCharFieldWidget
value_class = LocalizedStringValue
class LocalizedTextFieldForm(LocalizedFieldForm):
- """Form for a localized text field, allows editing
- the field in multiple languages."""
+ """Form for a localized text field, allows editing the field in multiple
+ languages."""
value_class = LocalizedStringValue
class LocalizedIntegerFieldForm(LocalizedFieldForm):
- """Form for a localized integer field, allows editing
- the field in multiple languages."""
+ """Form for a localized integer field, allows editing the field in multiple
+ languages."""
widget = AdminLocalizedIntegerFieldWidget
value_class = LocalizedIntegerValue
class LocalizedFileFieldForm(LocalizedFieldForm, forms.FileField):
- """Form for a localized file field, allows editing
- the field in multiple languages."""
+ """Form for a localized file field, allows editing the field in multiple
+ languages."""
widget = LocalizedFileWidget
field_class = forms.fields.FileField
value_class = LocalizedFileValue
def clean(self, value, initial=None):
- """
- Most part of this method is a copy of
- django.forms.MultiValueField.clean, with the exception of initial
- value handling (this need for correct processing FileField's).
+ """Most part of this method is a copy of
+ django.forms.MultiValueField.clean, with the exception of initial value
+ handling (this need for correct processing FileField's).
+
All original comments saved.
"""
if initial is None:
@@ -111,16 +123,21 @@ class LocalizedFileFieldForm(LocalizedFieldForm, forms.FileField):
clean_data = []
errors = []
if not value or isinstance(value, (list, tuple)):
- if (not value or not [v for v in value if
- v not in self.empty_values]) \
- and (not initial or not [v for v in initial if
- v not in self.empty_values]):
+ if (
+ not value
+ or not [v for v in value if v not in self.empty_values]
+ ) and (
+ not initial
+ or not [v for v in initial if v not in self.empty_values]
+ ):
if self.required:
- raise ValidationError(self.error_messages['required'],
- code='required')
+ raise ValidationError(
+ self.error_messages["required"], code="required"
+ )
else:
- raise ValidationError(self.error_messages['invalid'],
- code='invalid')
+ raise ValidationError(
+ self.error_messages["invalid"], code="invalid"
+ )
for i, field in enumerate(self.fields):
try:
field_value = value[i]
@@ -131,20 +148,23 @@ class LocalizedFileFieldForm(LocalizedFieldForm, forms.FileField):
except IndexError:
field_initial = None
- if field_value in self.empty_values and \
- field_initial in self.empty_values:
+ if (
+ field_value in self.empty_values
+ and field_initial in self.empty_values
+ ):
if self.require_all_fields:
# Raise a 'required' error if the MultiValueField is
# required and any field is empty.
if self.required:
- raise ValidationError(self.error_messages['required'],
- code='required')
+ raise ValidationError(
+ self.error_messages["required"], code="required"
+ )
elif field.required:
# Otherwise, add an 'incomplete' error to the list of
# collected errors and skip field cleaning, if a required
# field is empty.
- if field.error_messages['incomplete'] not in errors:
- errors.append(field.error_messages['incomplete'])
+ if field.error_messages["incomplete"] not in errors:
+ errors.append(field.error_messages["incomplete"])
continue
try:
clean_data.append(field.clean(field_value, field_initial))
diff --git a/localized_fields/lookups.py b/localized_fields/lookups.py
index 2875976..b85ac07 100644
--- a/localized_fields/lookups.py
+++ b/localized_fields/lookups.py
@@ -1,15 +1,29 @@
from django.conf import settings
from django.contrib.postgres.fields.hstore import KeyTransform
-from django.contrib.postgres.lookups import (SearchLookup, TrigramSimilar,
- Unaccent)
+from django.contrib.postgres.lookups import (
+ SearchLookup,
+ TrigramSimilar,
+ Unaccent,
+)
from django.db.models.expressions import Col
-from django.db.models.lookups import (Contains, EndsWith, Exact, IContains,
- IEndsWith, IExact, In, IRegex, IsNull,
- IStartsWith, Regex, StartsWith)
+from django.db.models.lookups import (
+ Contains,
+ EndsWith,
+ Exact,
+ IContains,
+ IEndsWith,
+ IExact,
+ In,
+ IRegex,
+ IsNull,
+ IStartsWith,
+ Regex,
+ StartsWith,
+)
from django.utils import translation
-class LocalizedLookupMixin():
+class LocalizedLookupMixin:
def process_lhs(self, qn, connection):
if isinstance(self.lhs, Col):
language = translation.get_language() or settings.LANGUAGE_CODE
diff --git a/localized_fields/migrations/0001_initial.py b/localized_fields/migrations/0001_initial.py
index 30c99ac..b22a0bf 100644
--- a/localized_fields/migrations/0001_initial.py
+++ b/localized_fields/migrations/0001_initial.py
@@ -6,9 +6,6 @@ from django.db import migrations
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
- operations = [
- HStoreExtension(),
- ]
+ operations = [HStoreExtension()]
diff --git a/localized_fields/mixins.py b/localized_fields/mixins.py
index 1402715..4483039 100644
--- a/localized_fields/mixins.py
+++ b/localized_fields/mixins.py
@@ -1,22 +1,18 @@
-from django.db import transaction
from django.conf import settings
+from django.db import transaction
from django.db.utils import IntegrityError
class AtomicSlugRetryMixin:
- """Makes :see:LocalizedUniqueSlugField work by retrying upon
- violation of the UNIQUE constraint."""
+ """Makes :see:LocalizedUniqueSlugField work by retrying upon violation of
+ the UNIQUE constraint."""
def save(self, *args, **kwargs):
"""Saves this model instance to the database."""
- max_retries = getattr(
- settings,
- 'LOCALIZED_FIELDS_MAX_RETRIES',
- 100
- )
+ max_retries = getattr(settings, "LOCALIZED_FIELDS_MAX_RETRIES", 100)
- if not hasattr(self, 'retries'):
+ if not hasattr(self, "retries"):
self.retries = 0
with transaction.atomic():
@@ -28,7 +24,7 @@ class AtomicSlugRetryMixin:
# 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 "slug" not in str(ex):
raise ex
if self.retries >= max_retries:
diff --git a/localized_fields/models.py b/localized_fields/models.py
index e298f04..7f30cb0 100644
--- a/localized_fields/models.py
+++ b/localized_fields/models.py
@@ -10,7 +10,8 @@ class LocalizedModel(AtomicSlugRetryMixin, PostgresModel):
from LocalizedModel. However, for certain features, this is required.
It is definitely needed for :see:LocalizedUniqueSlugField, unless you
- manually inherit from AtomicSlugRetryMixin."""
+ manually inherit from AtomicSlugRetryMixin.
+ """
class Meta:
abstract = True
diff --git a/localized_fields/util.py b/localized_fields/util.py
index ac9a722..933c1db 100644
--- a/localized_fields/util.py
+++ b/localized_fields/util.py
@@ -15,10 +15,7 @@ def get_language_codes() -> List[str]:
in your project.
"""
- return [
- lang_code
- for lang_code, _ in settings.LANGUAGES
- ]
+ return [lang_code for lang_code, _ in settings.LANGUAGES]
def resolve_object_property(obj, path: str):
@@ -38,7 +35,7 @@ def resolve_object_property(obj, path: str):
"""
value = obj
- for path_part in path.split('.'):
+ for path_part in path.split("."):
value = getattr(value, path_part)
return value
diff --git a/localized_fields/value.py b/localized_fields/value.py
index a1d7c29..310fc5a 100644
--- a/localized_fields/value.py
+++ b/localized_fields/value.py
@@ -1,7 +1,7 @@
-import deprecation
-
-from typing import Optional
from collections.abc import Iterable
+from typing import Optional
+
+import deprecation
from django.conf import settings
from django.utils import translation
@@ -9,9 +9,10 @@ from django.utils import translation
class LocalizedValue(dict):
"""Represents the value of a :see:LocalizedField."""
+
default_value = None
- def __init__(self, keys: dict=None):
+ def __init__(self, keys: dict = None):
"""Initializes a new instance of :see:LocalizedValue.
Arguments:
@@ -24,9 +25,8 @@ class LocalizedValue(dict):
super().__init__({})
self._interpret_value(keys)
- def get(self, language: str=None, default: str=None) -> str:
- """Gets the underlying value in the specified or
- primary language.
+ def get(self, language: str = None, default: str = None) -> str:
+ """Gets the underlying value in the specified or primary language.
Arguments:
language:
@@ -65,12 +65,12 @@ class LocalizedValue(dict):
contained in this instance.
"""
- path = 'localized_fields.value.%s' % self.__class__.__name__
+ path = "localized_fields.value.%s" % self.__class__.__name__
return path, [self.__dict__], {}
def _interpret_value(self, value):
- """Interprets a value passed in the constructor as
- a :see:LocalizedValue.
+ """Interprets a value passed in the constructor as a
+ :see:LocalizedValue.
If string:
Assumes it's the default language.
@@ -103,11 +103,10 @@ class LocalizedValue(dict):
self._interpret_value(val)
def translate(self) -> Optional[str]:
- """Gets the value in the current language or falls
- back to the next language if there's no value in the
- current language."""
+ """Gets the value in the current language or falls back to the next
+ language if there's no value in the current language."""
- fallbacks = getattr(settings, 'LOCALIZED_FIELDS_FALLBACKS', {})
+ fallbacks = getattr(settings, "LOCALIZED_FIELDS_FALLBACKS", {})
language = translation.get_language() or settings.LANGUAGE_CODE
languages = fallbacks.get(language, [settings.LANGUAGE_CODE])[:]
@@ -121,15 +120,13 @@ class LocalizedValue(dict):
return None
def __str__(self) -> str:
- """Gets the value in the current language or falls
- back to the next language if there's no value in the
- current language."""
+ """Gets the value in the current language or falls back to the next
+ language if there's no value in the current language."""
- return self.translate() or ''
+ return self.translate() or ""
def __eq__(self, other):
- """Compares :paramref:self to :paramref:other for
- equality.
+ """Compares :paramref:self to :paramref:other for equality.
Returns:
True when :paramref:self is equal to :paramref:other.
@@ -148,8 +145,7 @@ class LocalizedValue(dict):
return True
def __ne__(self, other):
- """Compares :paramref:self to :paramerf:other for
- in-equality.
+ """Compares :paramref:self to :paramerf:other for in-equality.
Returns:
True when :paramref:self is not equal to :paramref:other.
@@ -174,34 +170,43 @@ class LocalizedValue(dict):
def __repr__(self): # pragma: no cover
"""Gets a textual representation of this object."""
- return '%s<%s> 0x%s' % (self.__class__.__name__,
- self.__dict__, id(self))
+ return "%s<%s> 0x%s" % (
+ self.__class__.__name__,
+ self.__dict__,
+ id(self),
+ )
class LocalizedStringValue(LocalizedValue):
- default_value = ''
+ default_value = ""
class LocalizedFileValue(LocalizedValue):
def __getattr__(self, name: str):
- """Proxies access to attributes to attributes of LocalizedFile"""
+ """Proxies access to attributes to attributes of LocalizedFile."""
value = self.get(translation.get_language())
if hasattr(value, name):
return getattr(value, name)
- raise AttributeError("'{}' object has no attribute '{}'".
- format(self.__class__.__name__, name))
+ raise AttributeError(
+ "'{}' object has no attribute '{}'".format(
+ self.__class__.__name__, name
+ )
+ )
def __str__(self) -> str:
- """Returns string representation of value"""
+ """Returns string representation of value."""
return str(super().__str__())
- @deprecation.deprecated(deprecated_in='4.6', removed_in='5.0',
- current_version='4.6',
- details='Use the translate() function instead.')
+ @deprecation.deprecated(
+ deprecated_in="4.6",
+ removed_in="5.0",
+ current_version="4.6",
+ details="Use the translate() function instead.",
+ )
def localized(self):
- """Returns value for current language"""
+ """Returns value for current language."""
return self.get(translation.get_language())
@@ -212,11 +217,11 @@ class LocalizedIntegerValue(LocalizedValue):
default_value = None
def translate(self):
- """Gets the value in the current language, or
- in the configured fallbck language."""
+ """Gets the value in the current language, or in the configured fallbck
+ language."""
value = super().translate()
- if value is None or (isinstance(value, str) and value.strip() == ''):
+ if value is None or (isinstance(value, str) and value.strip() == ""):
return None
return int(value)
@@ -231,7 +236,7 @@ class LocalizedIntegerValue(LocalizedValue):
return int(value)
def __str__(self) -> str:
- """Returns string representation of value"""
+ """Returns string representation of value."""
value = self.translate()
- return str(value) if value is not None else ''
+ return str(value) if value is not None else ""
diff --git a/localized_fields/widgets.py b/localized_fields/widgets.py
index f48bf5a..12b3238 100644
--- a/localized_fields/widgets.py
+++ b/localized_fields/widgets.py
@@ -2,8 +2,8 @@ import copy
from typing import List
-from django.conf import settings
from django import forms
+from django.conf import settings
from django.contrib.admin import widgets
from .value import LocalizedValue
@@ -11,27 +11,27 @@ from .value import LocalizedValue
class LocalizedFieldWidget(forms.MultiWidget):
"""Widget that has an input box for every language."""
- template_name = 'localized_fields/multiwidget.html'
+
+ template_name = "localized_fields/multiwidget.html"
widget = forms.Textarea
def __init__(self, *args, **kwargs):
"""Initializes a new instance of :see:LocalizedFieldWidget."""
- initial_widgets = [
- copy.copy(self.widget)
- for _ in settings.LANGUAGES
- ]
+ initial_widgets = [copy.copy(self.widget) for _ in settings.LANGUAGES]
super().__init__(initial_widgets, *args, **kwargs)
- for ((lang_code, lang_name), widget) in zip(settings.LANGUAGES, self.widgets):
- widget.attrs['lang'] = lang_code
+ for ((lang_code, lang_name), widget) in zip(
+ settings.LANGUAGES, self.widgets
+ ):
+ widget.attrs["lang"] = lang_code
widget.lang_code = lang_code
widget.lang_name = lang_name
def decompress(self, value: LocalizedValue) -> List[str]:
- """Decompresses the specified value so
- it can be spread over the internal widgets.
+ """Decompresses the specified value so it can be spread over the
+ internal widgets.
Arguments:
value:
@@ -61,56 +61,62 @@ class LocalizedFieldWidget(forms.MultiWidget):
if not isinstance(value, list):
value = self.decompress(value)
- final_attrs = context['widget']['attrs']
- input_type = final_attrs.pop('type', None)
- id_ = final_attrs.get('id')
+ final_attrs = context["widget"]["attrs"]
+ input_type = final_attrs.pop("type", None)
+ id_ = final_attrs.get("id")
subwidgets = []
for i, widget in enumerate(self.widgets):
if input_type is not None:
widget.input_type = input_type
- widget_name = '%s_%s' % (name, i)
+ widget_name = "%s_%s" % (name, i)
try:
widget_value = value[i]
except IndexError:
widget_value = None
if id_:
widget_attrs = final_attrs.copy()
- widget_attrs['id'] = '%s_%s' % (id_, i)
+ widget_attrs["id"] = "%s_%s" % (id_, i)
else:
widget_attrs = final_attrs
- widget_attrs = self.build_widget_attrs(widget, widget_value, widget_attrs)
- widget_context = widget.get_context(widget_name, widget_value, widget_attrs)['widget']
- widget_context.update(dict(
- lang_code=widget.lang_code,
- lang_name=widget.lang_name
- ))
+ widget_attrs = self.build_widget_attrs(
+ widget, widget_value, widget_attrs
+ )
+ widget_context = widget.get_context(
+ widget_name, widget_value, widget_attrs
+ )["widget"]
+ widget_context.update(
+ dict(lang_code=widget.lang_code, lang_name=widget.lang_name)
+ )
subwidgets.append(widget_context)
- context['widget']['subwidgets'] = subwidgets
+ context["widget"]["subwidgets"] = subwidgets
return context
@staticmethod
def build_widget_attrs(widget, value, attrs):
attrs = dict(attrs) # Copy attrs to avoid modifying the argument.
- if (not widget.use_required_attribute(value) or not widget.is_required) \
- and 'required' in attrs:
- del attrs['required']
+ if (
+ not widget.use_required_attribute(value) or not widget.is_required
+ ) and "required" in attrs:
+ del attrs["required"]
return attrs
class LocalizedCharFieldWidget(LocalizedFieldWidget):
"""Widget that has an input box for every language."""
+
widget = forms.TextInput
class LocalizedFileWidget(LocalizedFieldWidget):
"""Widget that has an file input box for every language."""
+
widget = forms.ClearableFileInput
class AdminLocalizedFieldWidget(LocalizedFieldWidget):
- template_name = 'localized_fields/admin/widget.html'
+ template_name = "localized_fields/admin/widget.html"
widget = widgets.AdminTextareaWidget
diff --git a/setup.py b/setup.py
index 60c9df1..ff95946 100644
--- a/setup.py
+++ b/setup.py
@@ -35,17 +35,17 @@ with open(
setup(
- name='django-localized-fields',
- version='6.0b1',
- packages=find_packages(exclude=['tests']),
+ name="django-localized-fields",
+ version="6.0b1",
+ packages=find_packages(exclude=["tests"]),
include_package_data=True,
- license='MIT License',
- description='Implementation of localized model fields using PostgreSQL HStore fields.',
+ license="MIT License",
+ description="Implementation of localized model fields using PostgreSQL HStore fields.",
long_description=README,
- url='https://github.com/SectorLabs/django-localized-fields',
- author='Sector Labs',
- author_email='open-source@sectorlabs.ro',
- keywords=['django', 'localized', 'language', 'models', 'fields'],
+ url="https://github.com/SectorLabs/django-localized-fields",
+ author="Sector Labs",
+ author_email="open-source@sectorlabs.ro",
+ keywords=["django", "localized", "language", "models", "fields"],
classifiers=[
"Environment :: Web Environment",
"Framework :: Django",
@@ -77,11 +77,19 @@ setup(
"localized_fields",
"tests",
],
- ["autopep8", "-i", "-r", "setup.py", "localized_fields", "tests"],
+ [
+ "autopep8",
+ "-i",
+ "-r",
+ "setup.py",
+ "localized_fields",
+ "tests",
+ ],
],
),
"format": create_command(
- "Formats the code", [["black", "setup.py", "localized_fields", "tests"]]
+ "Formats the code",
+ [["black", "setup.py", "localized_fields", "tests"]],
),
"format_verify": create_command(
"Checks if the code is auto-formatted",
diff --git a/tests/data.py b/tests/data.py
index d074ca1..4803a00 100644
--- a/tests/data.py
+++ b/tests/data.py
@@ -2,12 +2,11 @@ from django.conf import settings
def get_init_values() -> dict:
- """Gets a test dictionary containing a key
- for every language."""
+ """Gets a test dictionary containing a key for every language."""
keys = {}
for lang_code, lang_name in settings.LANGUAGES:
- keys[lang_code] = 'value in %s' % lang_name
+ keys[lang_code] = "value in %s" % lang_name
return keys
diff --git a/tests/fake_model.py b/tests/fake_model.py
index 46526af..b35c457 100644
--- a/tests/fake_model.py
+++ b/tests/fake_model.py
@@ -1,20 +1,20 @@
import uuid
+from django.contrib.postgres.operations import HStoreExtension
from django.db import connection, migrations
from django.db.migrations.executor import MigrationExecutor
-from django.contrib.postgres.operations import HStoreExtension
from localized_fields.models import LocalizedModel
def define_fake_model(fields=None, model_base=LocalizedModel, meta_options={}):
- name = str(uuid.uuid4()).replace('-', '')[:8]
+ name = str(uuid.uuid4()).replace("-", "")[:8]
attributes = {
- 'app_label': 'tests',
- '__module__': __name__,
- '__name__': name,
- 'Meta': type('Meta', (object,), meta_options)
+ "app_label": "tests",
+ "__module__": __name__,
+ "__name__": name,
+ "Meta": type("Meta", (object,), meta_options),
}
if fields:
@@ -30,7 +30,6 @@ def get_fake_model(fields=None, model_base=LocalizedModel, meta_options={}):
model = define_fake_model(fields, model_base, meta_options)
class TestProject:
-
def clone(self, *_args, **_kwargs):
return self
@@ -44,7 +43,8 @@ def get_fake_model(fields=None, model_base=LocalizedModel, meta_options={}):
with connection.schema_editor() as schema_editor:
migration_executor = MigrationExecutor(schema_editor.connection)
migration_executor.apply_migration(
- TestProject(), TestMigration('eh', 'postgres_extra'))
+ TestProject(), TestMigration("eh", "postgres_extra")
+ )
schema_editor.create_model(model)
diff --git a/tests/test_admin.py b/tests/test_admin.py
index 6e0eb5a..e9b1692 100644
--- a/tests/test_admin.py
+++ b/tests/test_admin.py
@@ -4,9 +4,8 @@ from django.contrib.admin.checks import check_admin_app
from django.db import models
from django.test import TestCase
-from localized_fields.fields import LocalizedField
from localized_fields.admin import LocalizedFieldsAdminMixin
-
+from localized_fields.fields import LocalizedField
from tests.fake_model import get_fake_model
@@ -22,16 +21,13 @@ class LocalizedFieldsAdminMixinTestCase(TestCase):
super(LocalizedFieldsAdminMixinTestCase, cls).setUpClass()
- cls.TestRelModel = get_fake_model(
- {
- 'description': LocalizedField()
- }
- )
+ cls.TestRelModel = get_fake_model({"description": LocalizedField()})
cls.TestModel = get_fake_model(
{
- 'title': LocalizedField(),
- 'rel': models.ForeignKey(cls.TestRelModel,
- on_delete=models.CASCADE)
+ "title": LocalizedField(),
+ "rel": models.ForeignKey(
+ cls.TestRelModel, on_delete=models.CASCADE
+ ),
}
)
@@ -43,8 +39,8 @@ class LocalizedFieldsAdminMixinTestCase(TestCase):
@classmethod
def test_model_admin(cls):
- """Tests whether :see:LocalizedFieldsAdminMixin
- mixin are works with admin.ModelAdmin"""
+ """Tests whether :see:LocalizedFieldsAdminMixin mixin are works with
+ admin.ModelAdmin."""
@admin.register(cls.TestModel)
class TestModelAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
@@ -54,34 +50,32 @@ class LocalizedFieldsAdminMixinTestCase(TestCase):
@classmethod
def test_stackedmodel_admin(cls):
- """Tests whether :see:LocalizedFieldsAdminMixin mixin are works
- with admin.StackedInline"""
+ """Tests whether :see:LocalizedFieldsAdminMixin mixin are works with
+ admin.StackedInline."""
- class TestModelStackedInline(LocalizedFieldsAdminMixin,
- admin.StackedInline):
+ class TestModelStackedInline(
+ LocalizedFieldsAdminMixin, admin.StackedInline
+ ):
model = cls.TestModel
@admin.register(cls.TestRelModel)
class TestRelModelAdmin(admin.ModelAdmin):
- inlines = [
- TestModelStackedInline,
- ]
+ inlines = [TestModelStackedInline]
assert len(check_admin_app(apps.get_app_configs())) == 0
@classmethod
def test_tabularmodel_admin(cls):
- """Tests whether :see:LocalizedFieldsAdminMixin mixin are works
- with admin.TabularInline"""
+ """Tests whether :see:LocalizedFieldsAdminMixin mixin are works with
+ admin.TabularInline."""
- class TestModelTabularInline(LocalizedFieldsAdminMixin,
- admin.TabularInline):
+ class TestModelTabularInline(
+ LocalizedFieldsAdminMixin, admin.TabularInline
+ ):
model = cls.TestModel
@admin.register(cls.TestRelModel)
class TestRelModelAdmin(admin.ModelAdmin):
- inlines = [
- TestModelTabularInline,
- ]
+ inlines = [TestModelTabularInline]
assert len(check_admin_app(apps.get_app_configs())) == 0
diff --git a/tests/test_bleach_field.py b/tests/test_bleach_field.py
index 0901d3f..6d904f2 100644
--- a/tests/test_bleach_field.py
+++ b/tests/test_bleach_field.py
@@ -25,8 +25,8 @@ class LocalizedBleachFieldTestCase(TestCase):
"""Tests the :see:LocalizedBleachField class."""
def test_pre_save(self):
- """Tests whether the :see:pre_save function
- bleaches all values in a :see:LocalizedValue."""
+ """Tests whether the :see:pre_save function bleaches all values in a
+ :see:LocalizedValue."""
value = self._get_test_value()
model, field = self._get_test_model(value)
@@ -35,8 +35,8 @@ class LocalizedBleachFieldTestCase(TestCase):
self._validate(value, bleached_value)
def test_pre_save_none(self):
- """Tests whether the :see:pre_save function
- works properly when specifying :see:None."""
+ """Tests whether the :see:pre_save function works properly when
+ specifying :see:None."""
model, field = self._get_test_model(None)
@@ -44,9 +44,8 @@ class LocalizedBleachFieldTestCase(TestCase):
assert not bleached_value
def test_pre_save_none_values(self):
- """Tests whether the :see:pre_save function
- works properly when one of the languages has
- no text and is None."""
+ """Tests whether the :see:pre_save function works properly when one of
+ the languages has no text and is None."""
value = self._get_test_value()
value.set(settings.LANGUAGE_CODE, None)
@@ -58,14 +57,13 @@ class LocalizedBleachFieldTestCase(TestCase):
@staticmethod
def _get_test_model(value):
- """Gets a test model and a artifically
- constructed :see:LocalizedBleachField
- instance to test with."""
+ """Gets a test model and a artifically constructed
+ :see:LocalizedBleachField instance to test with."""
model = TestModel(value)
field = LocalizedBleachField()
- field.attname = 'value'
+ field.attname = "value"
return model, field
@staticmethod
@@ -75,14 +73,14 @@ class LocalizedBleachFieldTestCase(TestCase):
value = LocalizedValue()
for lang_code, lang_name in settings.LANGUAGES:
- value.set(lang_code, '' % lang_name)
+ value.set(lang_code, "" % lang_name)
return value
@staticmethod
def _validate(non_bleached_value, bleached_value):
- """Validates whether the specified non-bleached
- value ended up being correctly bleached.
+ """Validates whether the specified non-bleached value ended up being
+ correctly bleached.
Arguments:
non_bleached_value:
@@ -98,8 +96,7 @@ class LocalizedBleachFieldTestCase(TestCase):
continue
expected_value = bleach.clean(
- non_bleached_value.get(lang_code),
- get_bleach_default_options()
+ non_bleached_value.get(lang_code), get_bleach_default_options()
)
assert bleached_value.get(lang_code) == expected_value
diff --git a/tests/test_bulk.py b/tests/test_bulk.py
index 0d5cafc..7a7d5f8 100644
--- a/tests/test_bulk.py
+++ b/tests/test_bulk.py
@@ -7,26 +7,34 @@ from .fake_model import get_fake_model
class LocalizedBulkTestCase(TestCase):
- """Tests bulk operations with data structures provided
- by the django-localized-fields library."""
+ """Tests bulk operations with data structures provided by the django-
+ localized-fields library."""
@staticmethod
def test_localized_bulk_insert():
- """Tests whether bulk inserts work properly when using
- a :see:LocalizedUniqueSlugField in the model."""
+ """Tests whether bulk inserts work properly when using a
+ :see:LocalizedUniqueSlugField in the model."""
model = get_fake_model(
{
- 'name': LocalizedField(),
- 'slug': LocalizedUniqueSlugField(populate_from='name', include_time=True),
- 'score': models.IntegerField()
+ "name": LocalizedField(),
+ "slug": LocalizedUniqueSlugField(
+ populate_from="name", include_time=True
+ ),
+ "score": models.IntegerField(),
}
)
to_create = [
- model(name={'en': 'english name 1', 'ro': 'romanian name 1'}, score=1),
- model(name={'en': 'english name 2', 'ro': 'romanian name 2'}, score=2),
- model(name={'en': 'english name 3', 'ro': 'romanian name 3'}, score=3)
+ model(
+ name={"en": "english name 1", "ro": "romanian name 1"}, score=1
+ ),
+ model(
+ name={"en": "english name 2", "ro": "romanian name 2"}, score=2
+ ),
+ model(
+ name={"en": "english name 3", "ro": "romanian name 3"}, score=3
+ ),
]
model.objects.bulk_create(to_create)
@@ -34,9 +42,7 @@ class LocalizedBulkTestCase(TestCase):
for obj in to_create:
obj_db = model.objects.filter(
- name__en=obj.name.en,
- name__ro=obj.name.ro,
- score=obj.score
+ name__en=obj.name.en, name__ro=obj.name.ro, score=obj.score
).first()
assert obj_db
diff --git a/tests/test_expressions.py b/tests/test_expressions.py
index 79ce45f..0f6ade9 100644
--- a/tests/test_expressions.py
+++ b/tests/test_expressions.py
@@ -1,12 +1,12 @@
-from django.test import TestCase
-from django.db import models
-from django.utils import translation
from django.conf import settings
from django.contrib.postgres.aggregates import ArrayAgg
+from django.db import models
+from django.test import TestCase
+from django.utils import translation
+from localized_fields.expressions import LocalizedRef
from localized_fields.fields import LocalizedField
from localized_fields.value import LocalizedValue
-from localized_fields.expressions import LocalizedRef
from .fake_model import get_fake_model
@@ -24,15 +24,17 @@ class LocalizedExpressionsTestCase(TestCase):
super(LocalizedExpressionsTestCase, cls).setUpClass()
cls.TestModel1 = get_fake_model(
- {
- 'name': models.CharField(null=False, blank=False, max_length=255),
- }
+ {"name": models.CharField(null=False, blank=False, max_length=255)}
)
cls.TestModel2 = get_fake_model(
{
- 'text': LocalizedField(),
- 'other': models.ForeignKey(cls.TestModel1, related_name='features', on_delete=models.CASCADE)
+ "text": LocalizedField(),
+ "other": models.ForeignKey(
+ cls.TestModel1,
+ related_name="features",
+ on_delete=models.CASCADE,
+ ),
}
)
@@ -40,24 +42,28 @@ class LocalizedExpressionsTestCase(TestCase):
def test_localized_ref(cls):
"""Tests whether the :see:LocalizedRef expression properly works."""
- obj = cls.TestModel1.objects.create(name='bla bla')
+ obj = cls.TestModel1.objects.create(name="bla bla")
for i in range(0, 10):
cls.TestModel2.objects.create(
- text=LocalizedValue(dict(en='text_%d_en' % i, ro='text_%d_ro' % i, nl='text_%d_nl' % i)),
- other=obj
+ text=LocalizedValue(
+ dict(
+ en="text_%d_en" % i,
+ ro="text_%d_ro" % i,
+ nl="text_%d_nl" % i,
+ )
+ ),
+ other=obj,
)
def create_queryset(ref):
- return (
- cls.TestModel1.objects
- .annotate(mytexts=ref)
- .values_list('mytexts', flat=True)
+ return cls.TestModel1.objects.annotate(mytexts=ref).values_list(
+ "mytexts", flat=True
)
# assert that it properly selects the currently active language
for lang_code, _ in settings.LANGUAGES:
translation.activate(lang_code)
- queryset = create_queryset(LocalizedRef('features__text'))
+ queryset = create_queryset(LocalizedRef("features__text"))
for index, value in enumerate(queryset):
assert translation.get_language() in value
@@ -66,19 +72,21 @@ class LocalizedExpressionsTestCase(TestCase):
# ensure that the default language is used in case no
# language is active at all
translation.deactivate_all()
- queryset = create_queryset(LocalizedRef('features__text'))
+ queryset = create_queryset(LocalizedRef("features__text"))
for index, value in enumerate(queryset):
assert settings.LANGUAGE_CODE in value
assert str(index) in value
# ensures that overriding the language works properly
- queryset = create_queryset(LocalizedRef('features__text', 'ro'))
+ queryset = create_queryset(LocalizedRef("features__text", "ro"))
for index, value in enumerate(queryset):
- assert 'ro' in value
+ assert "ro" in value
assert str(index) in value
# ensures that using this in combination with ArrayAgg works properly
- queryset = create_queryset(ArrayAgg(LocalizedRef('features__text', 'ro'))).first()
+ queryset = create_queryset(
+ ArrayAgg(LocalizedRef("features__text", "ro"))
+ ).first()
assert isinstance(queryset, list)
for value in queryset:
- assert 'ro' in value
+ assert "ro" in value
diff --git a/tests/test_field.py b/tests/test_field.py
index de60523..8e72e9c 100644
--- a/tests/test_field.py
+++ b/tests/test_field.py
@@ -18,8 +18,8 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_init():
- """Tests whether the :see:__init__ function
- correctly handles parameters"""
+ """Tests whether the :see:__init__ function correctly handles
+ parameters."""
field = LocalizedField(blank=True)
assert field.required == []
@@ -28,16 +28,17 @@ class LocalizedFieldTestCase(TestCase):
assert field.required == [settings.LANGUAGE_CODE]
field = LocalizedField(required=True)
- assert field.required == [lang_code for lang_code, _ in
- settings.LANGUAGES]
+ assert field.required == [
+ lang_code for lang_code, _ in settings.LANGUAGES
+ ]
field = LocalizedField(required=False)
assert field.required == []
@staticmethod
def test_from_db_value():
- """Tests whether the :see:from_db_value function
- produces the expected :see:LocalizedValue."""
+ """Tests whether the :see:from_db_value function produces the expected
+ :see:LocalizedValue."""
input_data = get_init_values()
localized_value = LocalizedField().from_db_value(input_data)
@@ -47,8 +48,8 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_from_db_value_none():
- """Tests whether the :see:from_db_value function
- correctly handles None values."""
+ """Tests whether the :see:from_db_value function correctly handles None
+ values."""
localized_value = LocalizedField().from_db_value(None)
@@ -56,9 +57,8 @@ class LocalizedFieldTestCase(TestCase):
assert localized_value.get(lang_code) is None
def test_from_db_value_none_return_none(self):
- """Tests whether the :see:from_db_value function
- correctly handles None values when LOCALIZED_FIELDS_EXPERIMENTAL
- is set to True."""
+ """Tests whether the :see:from_db_value function correctly handles None
+ values when LOCALIZED_FIELDS_EXPERIMENTAL is set to True."""
with self.settings(LOCALIZED_FIELDS_EXPERIMENTAL=True):
localized_value = LocalizedField.from_db_value(None)
@@ -67,8 +67,8 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_to_python():
- """Tests whether the :see:to_python function
- produces the expected :see:LocalizedValue."""
+ """Tests whether the :see:to_python function produces the expected
+ :see:LocalizedValue."""
input_data = get_init_values()
localized_value = LocalizedField().to_python(input_data)
@@ -78,17 +78,16 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_to_python_non_json():
- """Tests whether the :see:to_python function
- properly handles a string that is not JSON."""
+ """Tests whether the :see:to_python function properly handles a string
+ that is not JSON."""
- localized_value = LocalizedField().to_python('my value')
- assert localized_value.get() == 'my value'
+ localized_value = LocalizedField().to_python("my value")
+ assert localized_value.get() == "my value"
@staticmethod
def test_to_python_none():
- """Tests whether the :see:to_python function
- produces the expected :see:LocalizedValue
- instance when it is passes None."""
+ """Tests whether the :see:to_python function produces the expected
+ :see:LocalizedValue instance when it is passes None."""
localized_value = LocalizedField().to_python(None)
assert localized_value
@@ -98,9 +97,8 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_to_python_non_dict():
- """Tests whether the :see:to_python function produces
- the expected :see:LocalizedValue when it is
- passed a non-dictionary value."""
+ """Tests whether the :see:to_python function produces the expected
+ :see:LocalizedValue when it is passed a non-dictionary value."""
localized_value = LocalizedField().to_python(list())
assert localized_value
@@ -110,9 +108,8 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_to_python_str():
- """Tests whether the :see:to_python function produces
- the expected :see:LocalizedValue when it is
- passed serialized string value."""
+ """Tests whether the :see:to_python function produces the expected
+ :see:LocalizedValue when it is passed serialized string value."""
serialized_str = json.dumps(get_init_values())
localized_value = LocalizedField().to_python(serialized_str)
@@ -124,8 +121,8 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_get_prep_value():
- """"Tests whether the :see:get_prep_value function
- produces the expected dictionary."""
+ """"Tests whether the :see:get_prep_value function produces the
+ expected dictionary."""
input_data = get_init_values()
localized_value = LocalizedValue(input_data)
@@ -138,25 +135,24 @@ class LocalizedFieldTestCase(TestCase):
@staticmethod
def test_get_prep_value_none():
- """Tests whether the :see:get_prep_value function
- produces the expected output when it is passed None."""
+ """Tests whether the :see:get_prep_value function produces the expected
+ output when it is passed None."""
output_data = LocalizedField().get_prep_value(None)
assert not output_data
@staticmethod
def test_get_prep_value_no_localized_value():
- """Tests whether the :see:get_prep_value function
- produces the expected output when it is passed a
- non-LocalizedValue value."""
+ """Tests whether the :see:get_prep_value function produces the expected
+ output when it is passed a non-LocalizedValue value."""
- output_data = LocalizedField().get_prep_value(['huh'])
+ output_data = LocalizedField().get_prep_value(["huh"])
assert not output_data
def test_get_prep_value_clean(self):
- """Tests whether the :see:get_prep_value produces
- None as the output when it is passed an empty, but
- valid LocalizedValue value but, only when null=True."""
+ """Tests whether the :see:get_prep_value produces None as the output
+ when it is passed an empty, but valid LocalizedValue value but, only
+ when null=True."""
localized_value = LocalizedValue()
@@ -165,17 +161,14 @@ class LocalizedFieldTestCase(TestCase):
assert not LocalizedField(null=True).get_prep_value(localized_value)
assert not LocalizedField().clean(None)
- assert not LocalizedField().clean(['huh'])
+ assert not LocalizedField().clean(["huh"])
@staticmethod
def test_formfield():
- """Tests whether the :see:formfield function
- correctly returns a valid form."""
+ """Tests whether the :see:formfield function correctly returns a valid
+ form."""
- assert isinstance(
- LocalizedField().formfield(),
- LocalizedFieldForm
- )
+ assert isinstance(LocalizedField().formfield(), LocalizedFieldForm)
# case optional filling
field = LocalizedField(blank=True, required=[])
@@ -190,7 +183,7 @@ class LocalizedFieldTestCase(TestCase):
assert not field.required
# case required for specific languages
- required_langs = ['ro', 'nl']
+ required_langs = ["ro", "nl"]
field = LocalizedField(blank=False, required=required_langs)
assert field.formfield().required
for field in field.formfield().fields:
@@ -206,31 +199,31 @@ class LocalizedFieldTestCase(TestCase):
assert field.required
def test_descriptor_user_defined_primary_key(self):
- """Tests that descriptor works even when primary key is user defined."""
- model = get_fake_model(dict(
- slug=models.SlugField(primary_key=True),
- title=LocalizedField()
- ))
+ """Tests that descriptor works even when primary key is user
+ defined."""
+ model = get_fake_model(
+ dict(
+ slug=models.SlugField(primary_key=True), title=LocalizedField()
+ )
+ )
- obj = model.objects.create(slug='test', title='test')
- assert obj.title == 'test'
+ obj = model.objects.create(slug="test", title="test")
+ assert obj.title == "test"
def test_required_all(self):
- """Tests whether passing required=True properly validates
- that all languages are filled in."""
+ """Tests whether passing required=True properly validates that all
+ languages are filled in."""
- model = get_fake_model(dict(
- title=LocalizedField(required=True)
- ))
+ model = get_fake_model(dict(title=LocalizedField(required=True)))
with self.assertRaises(IntegrityError):
- model.objects.create(title=dict(ro='romanian', nl='dutch'))
+ model.objects.create(title=dict(ro="romanian", nl="dutch"))
with self.assertRaises(IntegrityError):
- model.objects.create(title=dict(nl='dutch'))
+ model.objects.create(title=dict(nl="dutch"))
with self.assertRaises(IntegrityError):
- model.objects.create(title=dict(random='random'))
+ model.objects.create(title=dict(random="random"))
with self.assertRaises(IntegrityError):
model.objects.create(title=dict())
@@ -239,28 +232,27 @@ class LocalizedFieldTestCase(TestCase):
model.objects.create(title=None)
with self.assertRaises(IntegrityError):
- model.objects.create(title='')
+ model.objects.create(title="")
with self.assertRaises(IntegrityError):
- model.objects.create(title=' ')
+ model.objects.create(title=" ")
def test_required_some(self):
- """Tests whether passing an array to required,
- properly validates whether the specified languages
- are marked as required."""
+ """Tests whether passing an array to required, properly validates
+ whether the specified languages are marked as required."""
- model = get_fake_model(dict(
- title=LocalizedField(required=['nl', 'ro'])
- ))
+ model = get_fake_model(
+ dict(title=LocalizedField(required=["nl", "ro"]))
+ )
with self.assertRaises(IntegrityError):
- model.objects.create(title=dict(ro='romanian', nl='dutch'))
+ model.objects.create(title=dict(ro="romanian", nl="dutch"))
with self.assertRaises(IntegrityError):
- model.objects.create(title=dict(nl='dutch'))
+ model.objects.create(title=dict(nl="dutch"))
with self.assertRaises(IntegrityError):
- model.objects.create(title=dict(random='random'))
+ model.objects.create(title=dict(random="random"))
with self.assertRaises(IntegrityError):
model.objects.create(title=dict())
@@ -269,7 +261,7 @@ class LocalizedFieldTestCase(TestCase):
model.objects.create(title=None)
with self.assertRaises(IntegrityError):
- model.objects.create(title='')
+ model.objects.create(title="")
with self.assertRaises(IntegrityError):
- model.objects.create(title=' ')
+ model.objects.create(title=" ")
diff --git a/tests/test_file_field.py b/tests/test_file_field.py
index 529564e..5cf4f44 100644
--- a/tests/test_file_field.py
+++ b/tests/test_file_field.py
@@ -1,21 +1,21 @@
+import json
import os
+import pickle
import shutil
import tempfile as sys_tempfile
-import pickle
-import json
from django import forms
-from django.test import TestCase, override_settings
-from django.core.files.base import File, ContentFile
from django.core.files import temp as tempfile
+from django.core.files.base import ContentFile, File
+from django.test import TestCase, override_settings
+
from localized_fields.fields import LocalizedFileField
-from localized_fields.value import LocalizedValue
from localized_fields.fields.file_field import LocalizedFieldFile
from localized_fields.forms import LocalizedFileFieldForm
-from localized_fields.value import LocalizedFileValue
+from localized_fields.value import LocalizedFileValue, LocalizedValue
from localized_fields.widgets import LocalizedFileWidget
-from .fake_model import get_fake_model
+from .fake_model import get_fake_model
MEDIA_ROOT = sys_tempfile.mkdtemp()
@@ -30,11 +30,7 @@ class LocalizedFileFieldTestCase(TestCase):
super().setUpClass()
- cls.FileFieldModel = get_fake_model(
- {
- 'file': LocalizedFileField(),
- }
- )
+ cls.FileFieldModel = get_fake_model({"file": LocalizedFileField()})
if not os.path.isdir(MEDIA_ROOT):
os.makedirs(MEDIA_ROOT)
@@ -45,48 +41,49 @@ class LocalizedFileFieldTestCase(TestCase):
@classmethod
def test_assign(cls):
- """Tests whether the :see:LocalizedFileValueDescriptor works properly"""
+ """Tests whether the :see:LocalizedFileValueDescriptor works
+ properly."""
temp_file = tempfile.NamedTemporaryFile(dir=MEDIA_ROOT)
instance = cls.FileFieldModel()
- instance.file = {'en': temp_file.name}
+ instance.file = {"en": temp_file.name}
assert isinstance(instance.file.en, LocalizedFieldFile)
assert instance.file.en.name == temp_file.name
field_dump = pickle.dumps(instance.file)
instance = cls.FileFieldModel()
instance.file = pickle.loads(field_dump)
- assert instance.file.en.field == instance._meta.get_field('file')
+ assert instance.file.en.field == instance._meta.get_field("file")
assert instance.file.en.instance == instance
assert isinstance(instance.file.en, LocalizedFieldFile)
instance = cls.FileFieldModel()
- instance.file = {'en': ContentFile("test", "testfilename")}
+ instance.file = {"en": ContentFile("test", "testfilename")}
assert isinstance(instance.file.en, LocalizedFieldFile)
assert instance.file.en.name == "testfilename"
another_instance = cls.FileFieldModel()
- another_instance.file = {'ro': instance.file.en}
+ another_instance.file = {"ro": instance.file.en}
assert another_instance == another_instance.file.ro.instance
- assert another_instance.file.ro.lang == 'ro'
+ assert another_instance.file.ro.lang == "ro"
@classmethod
def test_save_form_data(cls):
- """Tests whether the :see:save_form_data function correctly set
- a valid value."""
+ """Tests whether the :see:save_form_data function correctly set a valid
+ value."""
instance = cls.FileFieldModel()
- data = LocalizedFileValue({'en': False})
- instance._meta.get_field('file').save_form_data(instance, data)
- assert instance.file.en == ''
+ data = LocalizedFileValue({"en": False})
+ instance._meta.get_field("file").save_form_data(instance, data)
+ assert instance.file.en == ""
@classmethod
def test_pre_save(cls):
"""Tests whether the :see:pre_save function works properly."""
instance = cls.FileFieldModel()
- instance.file = {'en': ContentFile("test", "testfilename")}
- instance._meta.get_field('file').pre_save(instance, False)
+ instance.file = {"en": ContentFile("test", "testfilename")}
+ instance._meta.get_field("file").pre_save(instance, False)
assert instance.file.en._committed is True
@classmethod
@@ -99,8 +96,8 @@ class LocalizedFileFieldTestCase(TestCase):
# Calling delete on an unset FileField should not call the file deletion
# process, but fail silently
instance.file.en.delete()
- instance.file.en.save('testfilename', temp_file)
- assert instance.file.en.name == 'testfilename'
+ instance.file.en.save("testfilename", temp_file)
+ assert instance.file.en.name == "testfilename"
instance.file.en.delete()
assert instance.file.en.name is None
@@ -110,27 +107,29 @@ class LocalizedFileFieldTestCase(TestCase):
works correctly."""
instance = cls.FileFieldModel()
- field = instance._meta.get_field('file')
- field.upload_to = '{lang}/'
- filename = field.generate_filename(instance, 'test', 'en')
- assert filename == 'en/test'
- field.upload_to = lambda instance, filename, lang: \
- '%s_%s' % (lang, filename)
- filename = field.generate_filename(instance, 'test', 'en')
- assert filename == 'en_test'
+ field = instance._meta.get_field("file")
+ field.upload_to = "{lang}/"
+ filename = field.generate_filename(instance, "test", "en")
+ assert filename == "en/test"
+ field.upload_to = lambda instance, filename, lang: "%s_%s" % (
+ lang,
+ filename,
+ )
+ filename = field.generate_filename(instance, "test", "en")
+ assert filename == "en_test"
@classmethod
- @override_settings(LANGUAGES=(('en', 'English'),))
+ @override_settings(LANGUAGES=(("en", "English"),))
def test_value_to_string(cls):
- """Tests whether the :see:LocalizedFileField
- class's :see:value_to_string function works properly."""
+ """Tests whether the :see:LocalizedFileField class's
+ :see:value_to_string function works properly."""
temp_file = File(tempfile.NamedTemporaryFile())
instance = cls.FileFieldModel()
- field = cls.FileFieldModel._meta.get_field('file')
- field.upload_to = ''
- instance.file.en.save('testfilename', temp_file)
- expected_value_to_string = json.dumps({'en': 'testfilename'})
+ field = cls.FileFieldModel._meta.get_field("file")
+ field.upload_to = ""
+ instance.file.en.save("testfilename", temp_file)
+ expected_value_to_string = json.dumps({"en": "testfilename"})
assert field.value_to_string(instance) == expected_value_to_string
@staticmethod
@@ -138,15 +137,15 @@ class LocalizedFileFieldTestCase(TestCase):
"""Tests whether the :see:get_prep_value function returns correctly
value."""
- value = LocalizedValue({'en': None})
+ value = LocalizedValue({"en": None})
assert LocalizedFileField().get_prep_value(None) is None
assert isinstance(LocalizedFileField().get_prep_value(value), dict)
- assert LocalizedFileField().get_prep_value(value)['en'] == ''
+ assert LocalizedFileField().get_prep_value(value)["en"] == ""
@staticmethod
def test_formfield():
- """Tests whether the :see:formfield function correctly returns
- a valid form."""
+ """Tests whether the :see:formfield function correctly returns a valid
+ form."""
form_field = LocalizedFileField().formfield()
assert isinstance(form_field, LocalizedFileFieldForm)
@@ -155,11 +154,13 @@ class LocalizedFileFieldTestCase(TestCase):
@staticmethod
def test_deconstruct():
- """Tests whether the :see:LocalizedFileField
- class's :see:deconstruct function works properly."""
+ """Tests whether the :see:LocalizedFileField class's :see:deconstruct
+ function works properly."""
name, path, args, kwargs = LocalizedFileField().deconstruct()
- assert 'upload_to' in kwargs
- assert 'storage' not in kwargs
- name, path, args, kwargs = LocalizedFileField(storage='test').deconstruct()
- assert 'storage' in kwargs
+ assert "upload_to" in kwargs
+ assert "storage" not in kwargs
+ name, path, args, kwargs = LocalizedFileField(
+ storage="test"
+ ).deconstruct()
+ assert "storage" in kwargs
diff --git a/tests/test_file_field_form.py b/tests/test_file_field_form.py
index 74dcc7c..ac48d86 100644
--- a/tests/test_file_field_form.py
+++ b/tests/test_file_field_form.py
@@ -16,7 +16,7 @@ class LocalizedFileFieldFormTestCase(TestCase):
with self.assertRaises(ValidationError):
formfield.clean([])
with self.assertRaises(ValidationError):
- formfield.clean([], {'en': None})
+ formfield.clean([], {"en": None})
with self.assertRaises(ValidationError):
formfield.clean("badvalue")
with self.assertRaises(ValidationError):
@@ -24,17 +24,17 @@ class LocalizedFileFieldFormTestCase(TestCase):
formfield.clean(value)
formfield = LocalizedFileFieldForm(required=False)
- formfield.clean([''] * len(settings.LANGUAGES))
- formfield.clean(['', ''], ['', ''])
+ formfield.clean([""] * len(settings.LANGUAGES))
+ formfield.clean(["", ""], ["", ""])
def test_bound_data(self):
"""Tests whether the :see:bound_data function is returns correctly
- value"""
+ value."""
formfield = LocalizedFileFieldForm()
- assert formfield.bound_data([''], None) == ['']
+ assert formfield.bound_data([""], None) == [""]
- initial = dict([(lang, '') for lang, _ in settings.LANGUAGES])
+ initial = dict([(lang, "") for lang, _ in settings.LANGUAGES])
value = [None] * len(settings.LANGUAGES)
- expected_value = [''] * len(settings.LANGUAGES)
+ expected_value = [""] * len(settings.LANGUAGES)
assert formfield.bound_data(value, initial) == expected_value
diff --git a/tests/test_file_widget.py b/tests/test_file_widget.py
index 87404ea..b1b1d75 100644
--- a/tests/test_file_widget.py
+++ b/tests/test_file_widget.py
@@ -9,16 +9,18 @@ class LocalizedFileWidgetTestCase(TestCase):
@staticmethod
def test_get_context():
- """Tests whether the :see:get_context correctly
- handles 'required' attribute, separately for each subwidget."""
+ """Tests whether the :see:get_context correctly handles 'required'
+ attribute, separately for each subwidget."""
widget = LocalizedFileWidget()
widget.widgets[0].is_required = True
widget.widgets[1].is_required = True
widget.widgets[2].is_required = False
- context = widget.get_context(name='test',
- value=LocalizedFileValue(dict(en='test')),
- attrs=dict(required=True))
- assert 'required' not in context['widget']['subwidgets'][0]['attrs']
- assert context['widget']['subwidgets'][1]['attrs']['required']
- assert 'required' not in context['widget']['subwidgets'][2]['attrs']
+ context = widget.get_context(
+ name="test",
+ value=LocalizedFileValue(dict(en="test")),
+ attrs=dict(required=True),
+ )
+ assert "required" not in context["widget"]["subwidgets"][0]["attrs"]
+ assert context["widget"]["subwidgets"][1]["attrs"]["required"]
+ assert "required" not in context["widget"]["subwidgets"][2]["attrs"]
diff --git a/tests/test_form.py b/tests/test_form.py
index 5c235fa..0131204 100644
--- a/tests/test_form.py
+++ b/tests/test_form.py
@@ -9,8 +9,8 @@ class LocalizedFieldFormTestCase(TestCase):
@staticmethod
def test_init():
- """Tests whether the constructor correctly
- creates a field for every language."""
+ """Tests whether the constructor correctly creates a field for every
+ language."""
# case required for specific language
form = LocalizedFieldForm(required=[settings.LANGUAGE_CODE])
@@ -42,8 +42,7 @@ class LocalizedFieldFormTestCase(TestCase):
@staticmethod
def test_compress():
- """Tests whether the :see:compress function
- is working properly."""
+ """Tests whether the :see:compress function is working properly."""
input_value = [lang_name for _, lang_name in settings.LANGUAGES]
output_value = LocalizedFieldForm().compress(input_value)
diff --git a/tests/test_integer_field.py b/tests/test_integer_field.py
index bd43541..61f0170 100644
--- a/tests/test_integer_field.py
+++ b/tests/test_integer_field.py
@@ -1,18 +1,18 @@
-from django.test import TestCase
-from django.db.utils import IntegrityError
from django.conf import settings
from django.db import connection
+from django.db.utils import IntegrityError
+from django.test import TestCase
from django.utils import translation
-from localized_fields.value import LocalizedIntegerValue
from localized_fields.fields import LocalizedIntegerField
+from localized_fields.value import LocalizedIntegerValue
from .fake_model import get_fake_model
class LocalizedIntegerFieldTestCase(TestCase):
- """Tests whether the :see:LocalizedIntegerField
- and :see:LocalizedIntegerValue works properly."""
+ """Tests whether the :see:LocalizedIntegerField and
+ :see:LocalizedIntegerValue works properly."""
TestModel = None
@@ -20,9 +20,7 @@ class LocalizedIntegerFieldTestCase(TestCase):
def setUpClass(cls):
super().setUpClass()
- cls.TestModel = get_fake_model({
- 'score': LocalizedIntegerField()
- })
+ cls.TestModel = get_fake_model({"score": LocalizedIntegerField()})
def test_basic(self):
"""Tests the basics of storing integer values."""
@@ -37,8 +35,8 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert obj.score.get(lang_code) == index + 1
def test_primary_language_required(self):
- """Tests whether the primary language is required by
- default and all other languages are optiona."""
+ """Tests whether the primary language is required by default and all
+ other languages are optiona."""
# not filling in anything should raise IntegrityError,
# the primary language is required
@@ -57,8 +55,8 @@ class LocalizedIntegerFieldTestCase(TestCase):
obj.save()
def test_default_value_none(self):
- """Tests whether the default value for optional languages
- is NoneType."""
+ """Tests whether the default value for optional languages is
+ NoneType."""
obj = self.TestModel()
obj.score.set(settings.LANGUAGE_CODE, 1234)
@@ -71,9 +69,8 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert obj.score.get(lang_code) is None
def test_translate(self):
- """Tests whether casting the value to an integer
- results in the value being returned in the currently
- active language as an integer."""
+ """Tests whether casting the value to an integer results in the value
+ being returned in the currently active language as an integer."""
obj = self.TestModel()
for index, (lang_code, _) in enumerate(settings.LANGUAGES):
@@ -87,10 +84,9 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert obj.score.translate() == index + 1
def test_translate_primary_fallback(self):
- """Tests whether casting the value to an integer
- results in the value begin returned in the active
- language and falls back to the primary language
- if there is no value in that language."""
+ """Tests whether casting the value to an integer results in the value
+ begin returned in the active language and falls back to the primary
+ language if there is no value in that language."""
obj = self.TestModel()
obj.score.set(settings.LANGUAGE_CODE, 25)
@@ -103,9 +99,8 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert int(obj.score) == 25
def test_get_default_value(self):
- """Tests whether getting the value in a specific
- language properly returns the specified default
- in case it is not available."""
+ """Tests whether getting the value in a specific language properly
+ returns the specified default in case it is not available."""
obj = self.TestModel()
obj.score.set(settings.LANGUAGE_CODE, 25)
@@ -115,12 +110,11 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert obj.score.get(secondary_language, 1337) == 1337
def test_completely_optional(self):
- """Tests whether having all languages optional
- works properly."""
+ """Tests whether having all languages optional works properly."""
- model = get_fake_model({
- 'score': LocalizedIntegerField(null=True, required=[], blank=True)
- })
+ model = get_fake_model(
+ {"score": LocalizedIntegerField(null=True, required=[], blank=True)}
+ )
obj = model()
obj.save()
@@ -129,19 +123,18 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert getattr(obj.score, lang_code) is None
def test_store_string(self):
- """Tests whether the field properly raises
- an error when trying to store a non-integer."""
+ """Tests whether the field properly raises an error when trying to
+ store a non-integer."""
for lang_code, _ in settings.LANGUAGES:
obj = self.TestModel()
with self.assertRaises(IntegrityError):
- obj.score.set(lang_code, 'haha')
+ obj.score.set(lang_code, "haha")
obj.save()
def test_none_if_illegal_value_stored(self):
- """Tests whether None is returned for a language
- if the value stored in the database is not an
- integer."""
+ """Tests whether None is returned for a language if the value stored in
+ the database is not an integer."""
obj = self.TestModel()
obj.score.set(settings.LANGUAGE_CODE, 25)
@@ -155,12 +148,15 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert obj.score.get(settings.LANGUAGE_CODE) is None
def test_default_value(self):
- """Tests whether a default is properly set
- when specified."""
+ """Tests whether a default is properly set when specified."""
- model = get_fake_model({
- 'score': LocalizedIntegerField(default={settings.LANGUAGE_CODE: 75})
- })
+ model = get_fake_model(
+ {
+ "score": LocalizedIntegerField(
+ default={settings.LANGUAGE_CODE: 75}
+ )
+ }
+ )
obj = model.objects.create()
assert obj.score.get(settings.LANGUAGE_CODE) == 75
@@ -177,16 +173,24 @@ class LocalizedIntegerFieldTestCase(TestCase):
assert obj.score.get(lang_code) is None
def test_default_value_update(self):
- """Tests whether a default is properly set
- when specified during updates."""
+ """Tests whether a default is properly set when specified during
+ updates."""
- model = get_fake_model({
- 'score': LocalizedIntegerField(default={settings.LANGUAGE_CODE: 75}, null=True)
- })
+ model = get_fake_model(
+ {
+ "score": LocalizedIntegerField(
+ default={settings.LANGUAGE_CODE: 75}, null=True
+ )
+ }
+ )
- obj = model.objects.create(score=LocalizedIntegerValue({settings.LANGUAGE_CODE: 35}))
+ obj = model.objects.create(
+ score=LocalizedIntegerValue({settings.LANGUAGE_CODE: 35})
+ )
assert obj.score.get(settings.LANGUAGE_CODE) == 35
- model.objects.update(score=LocalizedIntegerValue({settings.LANGUAGE_CODE: None}))
+ model.objects.update(
+ score=LocalizedIntegerValue({settings.LANGUAGE_CODE: None})
+ )
obj.refresh_from_db()
assert obj.score.get(settings.LANGUAGE_CODE) == 75
diff --git a/tests/test_lookups.py b/tests/test_lookups.py
index 056f6b4..ffa16f7 100644
--- a/tests/test_lookups.py
+++ b/tests/test_lookups.py
@@ -12,6 +12,7 @@ from .fake_model import get_fake_model
@override_settings(LOCALIZED_FIELDS_EXPERIMENTAL=True)
class LocalizedLookupsTestCase(TestCase):
"""Tests whether localized lookups properly work with."""
+
TestModel1 = None
@classmethod
@@ -21,31 +22,29 @@ class LocalizedLookupsTestCase(TestCase):
super(LocalizedLookupsTestCase, cls).setUpClass()
# reload app as setting has changed
- config = apps.get_app_config('localized_fields')
+ config = apps.get_app_config("localized_fields")
config.ready()
- cls.TestModel = get_fake_model(
- {
- 'text': LocalizedField(),
- }
- )
+ cls.TestModel = get_fake_model({"text": LocalizedField()})
def test_localized_lookup(self):
"""Tests whether localized lookup properly works."""
self.TestModel.objects.create(
- text=LocalizedValue(dict(en='text_en', ro='text_ro', nl='text_nl')),
+ text=LocalizedValue(dict(en="text_en", ro="text_ro", nl="text_nl"))
)
# assert that it properly lookups the currently active language
for lang_code, _ in settings.LANGUAGES:
translation.activate(lang_code)
- assert self.TestModel.objects.filter(text='text_' + lang_code).exists()
+ assert self.TestModel.objects.filter(
+ text="text_" + lang_code
+ ).exists()
# ensure that the default language is used in case no
# language is active at all
translation.deactivate_all()
- assert self.TestModel.objects.filter(text='text_en').exists()
+ assert self.TestModel.objects.filter(text="text_en").exists()
# ensure that hstore lookups still work
- assert self.TestModel.objects.filter(text__ro='text_ro').exists()
+ assert self.TestModel.objects.filter(text__ro="text_ro").exists()
diff --git a/tests/test_model.py b/tests/test_model.py
index 54f7ef7..72b218a 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -17,17 +17,12 @@ class LocalizedModelTestCase(TestCase):
super(LocalizedModelTestCase, cls).setUpClass()
- cls.TestModel = get_fake_model(
- {
- 'title': LocalizedField()
- }
- )
+ cls.TestModel = get_fake_model({"title": LocalizedField()})
@classmethod
def test_defaults(cls):
- """Tests whether all :see:LocalizedField
- fields are assigned an empty :see:LocalizedValue
- instance when the model is instanitiated."""
+ """Tests whether all :see:LocalizedField fields are assigned an empty
+ :see:LocalizedValue instance when the model is instanitiated."""
obj = cls.TestModel()
@@ -35,19 +30,18 @@ class LocalizedModelTestCase(TestCase):
@classmethod
def test_model_init_kwargs(cls):
- """Tests whether all :see:LocalizedField
- fields are assigned an empty :see:LocalizedValue
- instance when the model is instanitiated."""
+ """Tests whether all :see:LocalizedField fields are assigned an empty
+ :see:LocalizedValue instance when the model is instanitiated."""
data = {
- 'title': {
- 'en': 'english_title',
- 'ro': 'romanian_title',
- 'nl': 'dutch_title'
+ "title": {
+ "en": "english_title",
+ "ro": "romanian_title",
+ "nl": "dutch_title",
}
}
obj = cls.TestModel(**data)
assert isinstance(obj.title, LocalizedValue)
- assert obj.title.en == 'english_title'
- assert obj.title.ro == 'romanian_title'
- assert obj.title.nl == 'dutch_title'
+ assert obj.title.en == "english_title"
+ assert obj.title.ro == "romanian_title"
+ assert obj.title.nl == "dutch_title"
diff --git a/tests/test_query_set.py b/tests/test_query_set.py
index 2406404..675d6c8 100644
--- a/tests/test_query_set.py
+++ b/tests/test_query_set.py
@@ -16,30 +16,24 @@ class LocalizedQuerySetTestCase(TestCase):
super(LocalizedQuerySetTestCase, cls).setUpClass()
- cls.Model = get_fake_model(
- {
- 'title': LocalizedField(),
- }
- )
+ cls.Model = get_fake_model({"title": LocalizedField()})
@classmethod
def test_assign_raw_dict(cls):
inst = cls.Model()
- inst.title = dict(en='Bread', ro='Paine')
+ inst.title = dict(en="Bread", ro="Paine")
inst.save()
inst = cls.Model.objects.get(pk=inst.pk)
- assert inst.title.en == 'Bread'
- assert inst.title.ro == 'Paine'
+ assert inst.title.en == "Bread"
+ assert inst.title.ro == "Paine"
@classmethod
def test_assign_raw_dict_update(cls):
- inst = cls.Model.objects.create(
- title=dict(en='Bread', ro='Paine'))
+ inst = cls.Model.objects.create(title=dict(en="Bread", ro="Paine"))
- cls.Model.objects.update(
- title=dict(en='Beer', ro='Bere'))
+ cls.Model.objects.update(title=dict(en="Beer", ro="Bere"))
inst = cls.Model.objects.get(pk=inst.pk)
- assert inst.title.en == 'Beer'
- assert inst.title.ro == 'Bere'
+ assert inst.title.en == "Beer"
+ assert inst.title.ro == "Bere"
diff --git a/tests/test_slug_fields.py b/tests/test_slug_fields.py
index 96b0772..d3da9d0 100644
--- a/tests/test_slug_fields.py
+++ b/tests/test_slug_fields.py
@@ -1,16 +1,13 @@
import copy
from django import forms
-from django.db import models
from django.conf import settings
-from django.test import TestCase
+from django.db import models
from django.db.utils import IntegrityError
+from django.test import TestCase
from django.utils.text import slugify
-from localized_fields.fields import (
- LocalizedField,
- LocalizedUniqueSlugField
-)
+from localized_fields.fields import LocalizedField, LocalizedUniqueSlugField
from .fake_model import get_fake_model
@@ -29,23 +26,25 @@ class LocalizedSlugFieldTestCase(TestCase):
cls.Model = get_fake_model(
{
- 'title': LocalizedField(),
- 'name': models.CharField(max_length=255),
- 'slug': LocalizedUniqueSlugField(populate_from='title')
+ "title": LocalizedField(),
+ "name": models.CharField(max_length=255),
+ "slug": LocalizedUniqueSlugField(populate_from="title"),
}
)
@staticmethod
def test_unique_slug_with_time():
- """Tests whether the primary key is included in
- the slug when the 'use_pk' option is enabled."""
+ """Tests whether the primary key is included in the slug when the
+ 'use_pk' option is enabled."""
- title = 'myuniquetitle'
+ title = "myuniquetitle"
PkModel = get_fake_model(
{
- 'title': LocalizedField(),
- 'slug': LocalizedUniqueSlugField(populate_from='title', include_time=True)
+ "title": LocalizedField(),
+ "slug": LocalizedUniqueSlugField(
+ populate_from="title", include_time=True
+ ),
}
)
@@ -53,7 +52,7 @@ class LocalizedSlugFieldTestCase(TestCase):
obj.title.en = title
obj.save()
- assert obj.slug.en.startswith('%s-' % title)
+ assert obj.slug.en.startswith("%s-" % title)
@classmethod
def test_uniue_slug_no_change(cls):
@@ -61,12 +60,14 @@ class LocalizedSlugFieldTestCase(TestCase):
NoChangeSlugModel = get_fake_model(
{
- 'title': LocalizedField(),
- 'slug': LocalizedUniqueSlugField(populate_from='title', include_time=True)
+ "title": LocalizedField(),
+ "slug": LocalizedUniqueSlugField(
+ populate_from="title", include_time=True
+ ),
}
)
- title = 'myuniquetitle'
+ title = "myuniquetitle"
obj = NoChangeSlugModel()
obj.title.en = title
@@ -75,7 +76,7 @@ class LocalizedSlugFieldTestCase(TestCase):
old_slug_en = copy.deepcopy(obj.slug.en)
old_slug_nl = copy.deepcopy(obj.slug.nl)
- obj.title.nl += 'beer'
+ obj.title.nl += "beer"
obj.save()
assert old_slug_en == obj.slug.en
@@ -83,18 +84,20 @@ class LocalizedSlugFieldTestCase(TestCase):
@classmethod
def test_unique_slug_update(cls):
- obj = cls.Model.objects.create(title={settings.LANGUAGE_CODE: 'mytitle'})
- assert obj.slug.get() == 'mytitle'
- obj.title.set(settings.LANGUAGE_CODE, 'othertitle')
+ obj = cls.Model.objects.create(
+ title={settings.LANGUAGE_CODE: "mytitle"}
+ )
+ assert obj.slug.get() == "mytitle"
+ obj.title.set(settings.LANGUAGE_CODE, "othertitle")
obj.save()
- assert obj.slug.get() == 'othertitle'
+ assert obj.slug.get() == "othertitle"
@classmethod
def test_unique_slug_unique_max_retries(cls):
- """Tests whether the unique slug implementation doesn't
- try to find a slug forever and gives up after a while."""
+ """Tests whether the unique slug implementation doesn't try to find a
+ slug forever and gives up after a while."""
- title = 'myuniquetitle'
+ title = "myuniquetitle"
obj = cls.Model()
obj.title.en = title
@@ -111,106 +114,112 @@ class LocalizedSlugFieldTestCase(TestCase):
"""Tests whether the populating feature works correctly."""
obj = cls.Model()
- obj.title.en = 'this is my title'
+ obj.title.en = "this is my title"
obj.save()
- assert obj.slug.get('en') == slugify(obj.title)
+ assert obj.slug.get("en") == slugify(obj.title)
@classmethod
def test_populate_callable(cls):
- """Tests whether the populating feature works correctly
- when you specify a callable."""
+ """Tests whether the populating feature works correctly when you
+ specify a callable."""
def generate_slug(instance):
return instance.title
- get_fake_model({
- 'title': LocalizedField(),
- 'slug': LocalizedUniqueSlugField(populate_from=generate_slug)
- })
+ get_fake_model(
+ {
+ "title": LocalizedField(),
+ "slug": LocalizedUniqueSlugField(populate_from=generate_slug),
+ }
+ )
obj = cls.Model()
for lang_code, lang_name in settings.LANGUAGES:
- obj.title.set(lang_code, 'title %s' % lang_name)
+ obj.title.set(lang_code, "title %s" % lang_name)
obj.save()
for lang_code, lang_name in settings.LANGUAGES:
- assert obj.slug.get(lang_code) == 'title-%s' % lang_name.lower()
+ assert obj.slug.get(lang_code) == "title-%s" % lang_name.lower()
@staticmethod
def test_populate_multiple_from_fields():
- """Tests whether populating the slug from multiple
- fields works correctly."""
+ """Tests whether populating the slug from multiple fields works
+ correctly."""
model = get_fake_model(
{
- 'title': LocalizedField(),
- 'name': models.CharField(max_length=255),
- 'slug': LocalizedUniqueSlugField(populate_from=('title', 'name'))
+ "title": LocalizedField(),
+ "name": models.CharField(max_length=255),
+ "slug": LocalizedUniqueSlugField(
+ populate_from=("title", "name")
+ ),
}
)
obj = model()
for lang_code, lang_name in settings.LANGUAGES:
- obj.name = 'swen'
- obj.title.set(lang_code, 'title %s' % lang_name)
+ obj.name = "swen"
+ obj.title.set(lang_code, "title %s" % lang_name)
obj.save()
for lang_code, lang_name in settings.LANGUAGES:
- assert obj.slug.get(lang_code) == 'title-%s-swen' % lang_name.lower()
+ assert (
+ obj.slug.get(lang_code) == "title-%s-swen" % lang_name.lower()
+ )
@staticmethod
def test_populate_multiple_from_fields_fk():
- """Tests whether populating the slug from multiple
- fields works correctly."""
+ """Tests whether populating the slug from multiple fields works
+ correctly."""
- model_fk = get_fake_model(
- {
- 'name': LocalizedField(),
- }
- )
+ model_fk = get_fake_model({"name": LocalizedField()})
model = get_fake_model(
{
- 'title': LocalizedField(),
- 'other': models.ForeignKey(model_fk, on_delete=models.CASCADE),
- 'slug': LocalizedUniqueSlugField(populate_from=('title', 'other.name'))
+ "title": LocalizedField(),
+ "other": models.ForeignKey(model_fk, on_delete=models.CASCADE),
+ "slug": LocalizedUniqueSlugField(
+ populate_from=("title", "other.name")
+ ),
}
)
- other = model_fk.objects.create(name={settings.LANGUAGE_CODE: 'swen'})
+ other = model_fk.objects.create(name={settings.LANGUAGE_CODE: "swen"})
obj = model()
for lang_code, lang_name in settings.LANGUAGES:
obj.other_id = other.id
- obj.title.set(lang_code, 'title %s' % lang_name)
+ obj.title.set(lang_code, "title %s" % lang_name)
obj.save()
for lang_code, lang_name in settings.LANGUAGES:
- assert obj.slug.get(lang_code) == 'title-%s-swen' % lang_name.lower()
+ assert (
+ obj.slug.get(lang_code) == "title-%s-swen" % lang_name.lower()
+ )
@classmethod
def test_populate_multiple_languages(cls):
- """Tests whether the populating feature correctly
- works for all languages."""
+ """Tests whether the populating feature correctly works for all
+ languages."""
obj = cls.Model()
for lang_code, lang_name in settings.LANGUAGES:
- obj.title.set(lang_code, 'title %s' % lang_name)
+ obj.title.set(lang_code, "title %s" % lang_name)
obj.save()
for lang_code, lang_name in settings.LANGUAGES:
- assert obj.slug.get(lang_code) == 'title-%s' % lang_name.lower()
+ assert obj.slug.get(lang_code) == "title-%s" % lang_name.lower()
@classmethod
def test_unique_slug(cls):
"""Tests whether unique slugs are properly generated."""
- title = 'myuniquetitle'
+ title = "myuniquetitle"
obj = cls.Model()
obj.title.en = title
@@ -221,38 +230,36 @@ class LocalizedSlugFieldTestCase(TestCase):
another_obj.title.en = title
another_obj.save()
- assert another_obj.slug.en == '%s-%d' % (title, i)
+ assert another_obj.slug.en == "%s-%d" % (title, i)
@classmethod
def test_unique_slug_utf(cls):
- """Tests whether generating a slug works
- when the value consists completely out
- of non-ASCII characters."""
+ """Tests whether generating a slug works when the value consists
+ completely out of non-ASCII characters."""
obj = cls.Model()
- obj.title.en = 'مكاتب للايجار بشارع بورسعيد'
+ obj.title.en = "مكاتب للايجار بشارع بورسعيد"
obj.save()
- assert obj.slug.en == 'مكاتب-للايجار-بشارع-بورسعيد'
+ assert obj.slug.en == "مكاتب-للايجار-بشارع-بورسعيد"
@staticmethod
def test_deconstruct():
- """Tests whether the :see:deconstruct
- function properly retains options
+ """Tests whether the :see:deconstruct function properly retains options
specified in the constructor."""
- field = LocalizedUniqueSlugField(populate_from='title')
+ field = LocalizedUniqueSlugField(populate_from="title")
_, _, _, kwargs = field.deconstruct()
- assert 'populate_from' in kwargs
- assert kwargs['populate_from'] == field.populate_from
+ assert "populate_from" in kwargs
+ assert kwargs["populate_from"] == field.populate_from
@staticmethod
def test_formfield():
- """Tests whether the :see:formfield method
- returns a valid form field that is hidden."""
+ """Tests whether the :see:formfield method returns a valid form field
+ that is hidden."""
- form_field = LocalizedUniqueSlugField(populate_from='title').formfield()
+ form_field = LocalizedUniqueSlugField(populate_from="title").formfield()
assert isinstance(form_field, forms.CharField)
assert isinstance(form_field.widget, forms.HiddenInput)
diff --git a/tests/test_value.py b/tests/test_value.py
index c9a6622..ccd4e8c 100644
--- a/tests/test_value.py
+++ b/tests/test_value.py
@@ -1,7 +1,7 @@
-from django.db.models import F
from django.conf import settings
-from django.utils import translation
+from django.db.models import F
from django.test import TestCase, override_settings
+from django.utils import translation
from localized_fields.value import LocalizedValue
@@ -13,16 +13,14 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def tearDown():
- """Assures that the current language
- is set back to the default."""
+ """Assures that the current language is set back to the default."""
translation.activate(settings.LANGUAGE_CODE)
@staticmethod
def test_init():
- """Tests whether the __init__ function
- of the :see:LocalizedValue class works
- as expected."""
+ """Tests whether the __init__ function of the :see:LocalizedValue class
+ works as expected."""
keys = get_init_values()
value = LocalizedValue(keys)
@@ -32,9 +30,8 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_init_default_values():
- """Tests whether the __init__ function
- of the :see:LocalizedValue accepts the
- default value or an empty dict properly."""
+ """Tests whether the __init__ function of the :see:LocalizedValue
+ accepts the default value or an empty dict properly."""
value = LocalizedValue()
@@ -43,21 +40,20 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_init_array():
- """Tests whether the __init__ function
- of :see:LocalizedValue properly handles an
- array.
+ """Tests whether the __init__ function of :see:LocalizedValue properly
+ handles an array.
- Arrays can be passed to LocalizedValue as
- a result of a ArrayAgg operation."""
+ Arrays can be passed to LocalizedValue as a result of a ArrayAgg
+ operation.
+ """
- value = LocalizedValue(['my value'])
- assert value.get(settings.LANGUAGE_CODE) == 'my value'
+ value = LocalizedValue(["my value"])
+ assert value.get(settings.LANGUAGE_CODE) == "my value"
@staticmethod
def test_get_explicit():
- """Tests whether the the :see:LocalizedValue
- class's :see:get function works properly
- when specifying an explicit value."""
+ """Tests whether the the :see:LocalizedValue class's :see:get function
+ works properly when specifying an explicit value."""
keys = get_init_values()
localized_value = LocalizedValue(keys)
@@ -67,9 +63,8 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_get_default_language():
- """Tests whether the :see:LocalizedValue
- class's see:get function properly
- gets the value in the default language."""
+ """Tests whether the :see:LocalizedValue class's see:get function
+ properly gets the value in the default language."""
keys = get_init_values()
localized_value = LocalizedValue(keys)
@@ -80,8 +75,8 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_set():
- """Tests whether the :see:LocalizedValue
- class's see:set function works properly."""
+ """Tests whether the :see:LocalizedValue class's see:set function works
+ properly."""
localized_value = LocalizedValue()
@@ -92,21 +87,21 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_eq():
- """Tests whether the __eq__ operator
- of :see:LocalizedValue works properly."""
+ """Tests whether the __eq__ operator of :see:LocalizedValue works
+ properly."""
- a = LocalizedValue({'en': 'a', 'ar': 'b'})
- b = LocalizedValue({'en': 'a', 'ar': 'b'})
+ a = LocalizedValue({"en": "a", "ar": "b"})
+ b = LocalizedValue({"en": "a", "ar": "b"})
assert a == b
- b.en = 'b'
+ b.en = "b"
assert a != b
@staticmethod
def test_translate():
- """Tests whether the :see:LocalizedValue
- class's __str__ works properly."""
+ """Tests whether the :see:LocalizedValue class's __str__ works
+ properly."""
keys = get_init_values()
localized_value = LocalizedValue(keys)
@@ -117,15 +112,12 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_translate_fallback():
- """Tests whether the :see:LocalizedValue
- class's translate()'s fallback functionality
- works properly."""
+ """Tests whether the :see:LocalizedValue class's translate()'s fallback
+ functionality works properly."""
- test_value = 'myvalue'
+ test_value = "myvalue"
- localized_value = LocalizedValue({
- settings.LANGUAGE_CODE: test_value
- })
+ localized_value = LocalizedValue({settings.LANGUAGE_CODE: test_value})
other_language = settings.LANGUAGES[-1][0]
@@ -146,50 +138,44 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_translate_none():
- """Tests whether the :see:LocalizedValue
- class's translate() method properly returns
- None when there is no value."""
+ """Tests whether the :see:LocalizedValue class's translate() method
+ properly returns None when there is no value."""
# with no value, we always expect it to return None
localized_value = LocalizedValue()
assert localized_value.translate() is None
- assert str(localized_value) == ''
+ assert str(localized_value) == ""
# with no value for the default language, the default
# behavior is to return None, unless a custom fallback
# chain is configured, which there is not for this test
other_language = settings.LANGUAGES[-1][0]
- localized_value = LocalizedValue({
- other_language: 'hey'
- })
+ localized_value = LocalizedValue({other_language: "hey"})
translation.activate(settings.LANGUAGE_CODE)
assert localized_value.translate() is None
- assert str(localized_value) == ''
+ assert str(localized_value) == ""
@staticmethod
def test_translate_fallback_custom_fallback():
- """Tests whether the :see:LocalizedValue class's
- translate()'s fallback functionality properly respects
- the LOCALIZED_FIELDS_FALLBACKS setting."""
+ """Tests whether the :see:LocalizedValue class's translate()'s fallback
+ functionality properly respects the LOCALIZED_FIELDS_FALLBACKS
+ setting."""
- fallbacks = {
- 'nl': ['ro']
- }
+ fallbacks = {"nl": ["ro"]}
- localized_value = LocalizedValue({
- settings.LANGUAGE_CODE: settings.LANGUAGE_CODE,
- 'ro': 'ro'
- })
+ localized_value = LocalizedValue(
+ {settings.LANGUAGE_CODE: settings.LANGUAGE_CODE, "ro": "ro"}
+ )
with override_settings(LOCALIZED_FIELDS_FALLBACKS=fallbacks):
- with translation.override('nl'):
- assert localized_value.translate() == 'ro'
+ with translation.override("nl"):
+ assert localized_value.translate() == "ro"
@staticmethod
def test_deconstruct():
- """Tests whether the :see:LocalizedValue
- class's :see:deconstruct function works properly."""
+ """Tests whether the :see:LocalizedValue class's :see:deconstruct
+ function works properly."""
keys = get_init_values()
value = LocalizedValue(keys)
@@ -200,16 +186,16 @@ class LocalizedValueTestCase(TestCase):
@staticmethod
def test_construct_string():
- """Tests whether the :see:LocalizedValue's constructor
- assumes the primary language when passing a single string."""
+ """Tests whether the :see:LocalizedValue's constructor assumes the
+ primary language when passing a single string."""
- value = LocalizedValue('beer')
- assert value.get(settings.LANGUAGE_CODE) == 'beer'
+ value = LocalizedValue("beer")
+ assert value.get(settings.LANGUAGE_CODE) == "beer"
@staticmethod
def test_construct_expression():
- """Tests whether passing expressions as values
- works properly and are not converted to string."""
+ """Tests whether passing expressions as values works properly and are
+ not converted to string."""
- value = LocalizedValue(dict(en=F('other')))
+ value = LocalizedValue(dict(en=F("other")))
assert isinstance(value.en, F)
diff --git a/tests/test_widget.py b/tests/test_widget.py
index 87ddacd..ccd6a07 100644
--- a/tests/test_widget.py
+++ b/tests/test_widget.py
@@ -1,4 +1,5 @@
import re
+
from django.conf import settings
from django.test import TestCase
@@ -11,8 +12,7 @@ class LocalizedFieldWidgetTestCase(TestCase):
@staticmethod
def test_widget_creation():
- """Tests whether a widget is created for every
- language correctly."""
+ """Tests whether a widget is created for every language correctly."""
widget = LocalizedFieldWidget()
assert len(widget.widgets) == len(settings.LANGUAGES)
@@ -20,9 +20,8 @@ class LocalizedFieldWidgetTestCase(TestCase):
@staticmethod
def test_decompress():
- """Tests whether a :see:LocalizedValue instance
- can correctly be "decompressed" over the available
- widgets."""
+ """Tests whether a :see:LocalizedValue instance can correctly be
+ "decompressed" over the available widgets."""
localized_value = LocalizedValue()
for lang_code, lang_name in settings.LANGUAGES:
@@ -31,13 +30,15 @@ class LocalizedFieldWidgetTestCase(TestCase):
widget = LocalizedFieldWidget()
decompressed_values = widget.decompress(localized_value)
- for (lang_code, _), value in zip(settings.LANGUAGES, decompressed_values):
+ for (lang_code, _), value in zip(
+ settings.LANGUAGES, decompressed_values
+ ):
assert localized_value.get(lang_code) == value
@staticmethod
def test_decompress_none():
- """Tests whether the :see:LocalizedFieldWidget correctly
- handles :see:None."""
+ """Tests whether the :see:LocalizedFieldWidget correctly handles
+ :see:None."""
widget = LocalizedFieldWidget()
decompressed_values = widget.decompress(None)
@@ -47,16 +48,17 @@ class LocalizedFieldWidgetTestCase(TestCase):
@staticmethod
def test_get_context_required():
- """Tests whether the :see:get_context correctly
- handles 'required' attribute, separately for each subwidget."""
+ """Tests whether the :see:get_context correctly handles 'required'
+ attribute, separately for each subwidget."""
widget = LocalizedFieldWidget()
widget.widgets[0].is_required = True
widget.widgets[1].is_required = False
- context = widget.get_context(name='test', value=LocalizedValue(),
- attrs=dict(required=True))
- assert context['widget']['subwidgets'][0]['attrs']['required']
- assert 'required' not in context['widget']['subwidgets'][1]['attrs']
+ context = widget.get_context(
+ name="test", value=LocalizedValue(), attrs=dict(required=True)
+ )
+ assert context["widget"]["subwidgets"][0]["attrs"]["required"]
+ assert "required" not in context["widget"]["subwidgets"][1]["attrs"]
@staticmethod
def test_get_context_langs():
@@ -64,20 +66,20 @@ class LocalizedFieldWidgetTestCase(TestCase):
'lang_name' attribute for each subwidget."""
widget = LocalizedFieldWidget()
- context = widget.get_context(name='test', value=LocalizedValue(),
- attrs=dict())
- subwidgets_context = context['widget']['subwidgets']
+ context = widget.get_context(
+ name="test", value=LocalizedValue(), attrs=dict()
+ )
+ subwidgets_context = context["widget"]["subwidgets"]
for widget, context in zip(widget.widgets, subwidgets_context):
- assert 'lang_code' in context
- assert 'lang_name' in context
- assert widget.lang_code == context['lang_code']
- assert widget.lang_name == context['lang_name']
+ assert "lang_code" in context
+ assert "lang_name" in context
+ assert widget.lang_code == context["lang_code"]
+ assert widget.lang_name == context["lang_name"]
@staticmethod
def test_render():
- """Tests whether the :see:LocalizedFieldWidget correctly
- render."""
+ """Tests whether the :see:LocalizedFieldWidget correctly render."""
widget = LocalizedFieldWidget()
- output = widget.render(name='title', value=None)
- assert bool(re.search('