From 6d01cffbc0f7a15728a4b1a8d883111b35ca88be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Hubscher?= Date: Tue, 7 Oct 2025 11:25:07 +0200 Subject: [PATCH] Use double quotes --- constance/admin.py | 84 ++++---- constance/apps.py | 8 +- constance/backends/database.py | 10 +- constance/backends/redisd.py | 4 +- constance/base.py | 2 +- constance/checks.py | 22 +- constance/codecs.py | 44 ++-- constance/context_processors.py | 2 +- constance/forms.py | 64 +++--- constance/management/commands/constance.py | 44 ++-- constance/migrations/0001_initial.py | 14 +- .../migrations/0002_migrate_from_old_table.py | 14 +- constance/migrations/0003_drop_pickle.py | 16 +- constance/models.py | 8 +- constance/settings.py | 28 +-- constance/test/__init__.py | 2 +- constance/test/pytest.py | 8 +- constance/test/unittest.py | 4 +- constance/utils.py | 4 +- docs/conf.py | 64 +++--- docs/extensions/settings.py | 6 +- .../apps/catalog/migrations/0001_initial.py | 6 +- .../apps/storage/migrations/0001_initial.py | 16 +- example/cheeseshop/apps/storage/models.py | 4 +- example/cheeseshop/fields.py | 2 +- example/cheeseshop/settings.py | 148 +++++++------- example/cheeseshop/urls.py | 2 +- example/cheeseshop/wsgi.py | 2 +- example/manage.py | 4 +- pyproject.toml | 1 - tests/backends/test_database.py | 2 +- tests/backends/test_memory.py | 2 +- tests/backends/test_redis.py | 4 +- tests/settings.py | 134 ++++++------ tests/storage.py | 58 +++--- tests/test_admin.py | 190 +++++++++--------- tests/test_checks.py | 12 +- tests/test_cli.py | 56 +++--- tests/test_codecs.py | 40 ++-- tests/test_form.py | 22 +- tests/test_pytest_overrides.py | 6 +- tests/test_utils.py | 76 +++---- tests/urls.py | 2 +- 43 files changed, 620 insertions(+), 621 deletions(-) diff --git a/constance/admin.py b/constance/admin.py index 862759a..43715f0 100644 --- a/constance/admin.py +++ b/constance/admin.py @@ -25,7 +25,7 @@ config = LazyConfig() class ConstanceAdmin(admin.ModelAdmin): - change_list_template = 'admin/constance/change_list.html' + change_list_template = "admin/constance/change_list.html" change_list_form = ConstanceForm def __init__(self, model, admin_site): @@ -33,10 +33,10 @@ class ConstanceAdmin(admin.ModelAdmin): super().__init__(model, admin_site) def get_urls(self): - info = f'{self.model._meta.app_label}_{self.model._meta.module_name}' + info = f"{self.model._meta.app_label}_{self.model._meta.module_name}" return [ - path('', self.admin_site.admin_view(self.changelist_view), name=f'{info}_changelist'), - path('', self.admin_site.admin_view(self.changelist_view), name=f'{info}_add'), + path("", self.admin_site.admin_view(self.changelist_view), name=f"{info}_changelist"), + path("", self.admin_site.admin_view(self.changelist_view), name=f"{info}_add"), ] def get_config_value(self, name, options, form, initial): @@ -52,23 +52,23 @@ class ConstanceAdmin(admin.ModelAdmin): form_field = form[name] config_value = { - 'name': name, - 'default': localize(default), - 'raw_default': default, - 'help_text': _(help_text), - 'value': localize(value), - 'modified': localize(value) != localize(default), - 'form_field': form_field, - 'is_date': isinstance(default, date), - 'is_datetime': isinstance(default, datetime), - 'is_checkbox': isinstance(form_field.field.widget, forms.CheckboxInput), - 'is_file': isinstance(form_field.field.widget, forms.FileInput), + "name": name, + "default": localize(default), + "raw_default": default, + "help_text": _(help_text), + "value": localize(value), + "modified": localize(value) != localize(default), + "form_field": form_field, + "is_date": isinstance(default, date), + "is_datetime": isinstance(default, datetime), + "is_checkbox": isinstance(form_field.field.widget, forms.CheckboxInput), + "is_file": isinstance(form_field.field.widget, forms.FileInput), } if field_type and field_type in settings.ADDITIONAL_FIELDS: serialized_default = form[name].field.prepare_value(default) - config_value['default'] = serialized_default - config_value['raw_default'] = serialized_default - config_value['value'] = form[name].field.prepare_value(value) + config_value["default"] = serialized_default + config_value["raw_default"] = serialized_default + config_value["value"] = form[name].field.prepare_value(value) return config_value @@ -85,26 +85,26 @@ class ConstanceAdmin(admin.ModelAdmin): initial = get_values() form_cls = self.get_changelist_form(request) form = form_cls(initial=initial, request=request) - if request.method == 'POST' and request.user.has_perm('constance.change_config'): + if request.method == "POST" and request.user.has_perm("constance.change_config"): form = form_cls(data=request.POST, files=request.FILES, initial=initial, request=request) if form.is_valid(): form.save() - messages.add_message(request, messages.SUCCESS, _('Live settings updated successfully.')) - return HttpResponseRedirect('.') - messages.add_message(request, messages.ERROR, _('Failed to update live settings.')) + messages.add_message(request, messages.SUCCESS, _("Live settings updated successfully.")) + return HttpResponseRedirect(".") + messages.add_message(request, messages.ERROR, _("Failed to update live settings.")) context = dict( self.admin_site.each_context(request), config_values=[], title=self.model._meta.app_config.verbose_name, - app_label='constance', + app_label="constance", opts=self.model._meta, form=form, media=self.media + form.media, - icon_type='svg', + icon_type="svg", django_version=get_version(), ) for name, options in settings.CONFIG.items(): - context['config_values'].append(self.get_config_value(name, options, form, initial)) + context["config_values"].append(self.get_config_value(name, options, form, initial)) if settings.CONFIG_FIELDSETS: if isinstance(settings.CONFIG_FIELDSETS, dict): @@ -112,11 +112,11 @@ class ConstanceAdmin(admin.ModelAdmin): else: fieldset_items = settings.CONFIG_FIELDSETS - context['fieldsets'] = [] + context["fieldsets"] = [] for fieldset_title, fieldset_data in fieldset_items: if isinstance(fieldset_data, dict): - fields_list = fieldset_data['fields'] - collapse = fieldset_data.get('collapse', False) + fields_list = fieldset_data["fields"] + collapse = fieldset_data.get("collapse", False) else: fields_list = fieldset_data collapse = False @@ -124,8 +124,8 @@ class ConstanceAdmin(admin.ModelAdmin): absent_fields = [field for field in fields_list if field not in settings.CONFIG] if any(absent_fields): raise ValueError( - 'CONSTANCE_CONFIG_FIELDSETS contains field(s) that does not exist(s): {}'.format( - ', '.join(absent_fields) + "CONSTANCE_CONFIG_FIELDSETS contains field(s) that does not exist(s): {}".format( + ", ".join(absent_fields) ) ) @@ -135,16 +135,16 @@ class ConstanceAdmin(admin.ModelAdmin): options = settings.CONFIG.get(name) if options: config_values.append(self.get_config_value(name, options, form, initial)) - fieldset_context = {'title': fieldset_title, 'config_values': config_values} + fieldset_context = {"title": fieldset_title, "config_values": config_values} if collapse: - fieldset_context['collapse'] = True - context['fieldsets'].append(fieldset_context) + fieldset_context["collapse"] = True + context["fieldsets"].append(fieldset_context) if not isinstance(settings.CONFIG_FIELDSETS, (OrderedDict, tuple)): - context['fieldsets'].sort(key=itemgetter('title')) + context["fieldsets"].sort(key=itemgetter("title")) if not isinstance(settings.CONFIG, OrderedDict): - context['config_values'].sort(key=itemgetter('name')) + context["config_values"].sort(key=itemgetter("name")) request.current_app = self.admin_site.name return TemplateResponse(request, self.change_list_template, context) @@ -162,11 +162,11 @@ class ConstanceAdmin(admin.ModelAdmin): class Config: class Meta: - app_label = 'constance' - object_name = 'Config' + app_label = "constance" + object_name = "Config" concrete_model = None - model_name = module_name = 'config' - verbose_name_plural = _('config') + model_name = module_name = "config" + verbose_name_plural = _("config") abstract = False swapped = False is_composite_pk = False @@ -175,7 +175,7 @@ class Config: return False def get_change_permission(self): - return f'change_{self.model_name}' + return f"change_{self.model_name}" @property def app_config(self): @@ -183,11 +183,11 @@ class Config: @property def label(self): - return f'{self.app_label}.{self.object_name}' + return f"{self.app_label}.{self.object_name}" @property def label_lower(self): - return f'{self.app_label}.{self.model_name}' + return f"{self.app_label}.{self.model_name}" _meta = Meta() diff --git a/constance/apps.py b/constance/apps.py index 950be0e..116a64f 100644 --- a/constance/apps.py +++ b/constance/apps.py @@ -6,9 +6,9 @@ from constance.checks import check_fieldsets class ConstanceConfig(AppConfig): - name = 'constance' - verbose_name = _('Constance') - default_auto_field = 'django.db.models.AutoField' + name = "constance" + verbose_name = _("Constance") + default_auto_field = "django.db.models.AutoField" def ready(self): - checks.register(check_fieldsets, 'constance') + checks.register(check_fieldsets, "constance") diff --git a/constance/backends/database.py b/constance/backends/database.py index be3e028..5d4b225 100644 --- a/constance/backends/database.py +++ b/constance/backends/database.py @@ -22,7 +22,7 @@ class DatabaseBackend(Backend): self._model = Constance self._prefix = settings.DATABASE_PREFIX self._autofill_timeout = settings.DATABASE_CACHE_AUTOFILL_TIMEOUT - self._autofill_cachekey = 'autofilled' + self._autofill_cachekey = "autofilled" if self._model._meta.app_config is None: raise ImproperlyConfigured( @@ -34,9 +34,9 @@ class DatabaseBackend(Backend): self._cache = caches[settings.DATABASE_CACHE_BACKEND] if isinstance(self._cache, LocMemCache): raise ImproperlyConfigured( - 'The CONSTANCE_DATABASE_CACHE_BACKEND setting refers to a ' + "The CONSTANCE_DATABASE_CACHE_BACKEND setting refers to a " f"subclass of Django's local-memory backend ({settings.DATABASE_CACHE_BACKEND!r}). Please " - 'set it to a backend that supports cross-process caching.' + "set it to a backend that supports cross-process caching." ) else: self._cache = None @@ -45,7 +45,7 @@ class DatabaseBackend(Backend): post_save.connect(self.clear, sender=self._model) def add_prefix(self, key): - return f'{self._prefix}{key}' + return f"{self._prefix}{key}" def autofill(self): if not self._autofill_timeout or not self._cache: @@ -111,7 +111,7 @@ class DatabaseBackend(Backend): if not created: old_value = loads(constance.value) constance.value = dumps(value) - constance.save(update_fields=['value']) + constance.save(update_fields=["value"]) else: old_value = None diff --git a/constance/backends/redisd.py b/constance/backends/redisd.py index cb5bef7..22e8f33 100644 --- a/constance/backends/redisd.py +++ b/constance/backends/redisd.py @@ -23,14 +23,14 @@ class RedisBackend(Backend): try: import redis except ImportError: - raise ImproperlyConfigured('The Redis backend requires redis-py to be installed.') from None + raise ImproperlyConfigured("The Redis backend requires redis-py to be installed.") from None if isinstance(settings.REDIS_CONNECTION, str): self._rd = redis.from_url(settings.REDIS_CONNECTION) else: self._rd = redis.Redis(**settings.REDIS_CONNECTION) def add_prefix(self, key): - return f'{self._prefix}{key}' + return f"{self._prefix}{key}" def get(self, key): value = self._rd.get(self.add_prefix(key)) diff --git a/constance/base.py b/constance/base.py index 614ed3e..92e6dfa 100644 --- a/constance/base.py +++ b/constance/base.py @@ -6,7 +6,7 @@ class Config: """The global config wrapper that handles the backend.""" def __init__(self): - super().__setattr__('_backend', utils.import_module_attr(settings.BACKEND)()) + super().__setattr__("_backend", utils.import_module_attr(settings.BACKEND)()) def __getattr__(self, key): try: diff --git a/constance/checks.py b/constance/checks.py index 9b3b1ba..1ad2034 100644 --- a/constance/checks.py +++ b/constance/checks.py @@ -14,22 +14,22 @@ def check_fieldsets(*args, **kwargs) -> list[CheckMessage]: errors = [] - if hasattr(settings, 'CONFIG_FIELDSETS') and settings.CONFIG_FIELDSETS: + if hasattr(settings, "CONFIG_FIELDSETS") and settings.CONFIG_FIELDSETS: missing_keys, extra_keys = get_inconsistent_fieldnames() if missing_keys: check = checks.Warning( - _('CONSTANCE_CONFIG_FIELDSETS is missing field(s) that exists in CONSTANCE_CONFIG.'), - hint=', '.join(sorted(missing_keys)), - obj='settings.CONSTANCE_CONFIG', - id='constance.E001', + _("CONSTANCE_CONFIG_FIELDSETS is missing field(s) that exists in CONSTANCE_CONFIG."), + hint=", ".join(sorted(missing_keys)), + obj="settings.CONSTANCE_CONFIG", + id="constance.E001", ) errors.append(check) if extra_keys: check = checks.Warning( - _('CONSTANCE_CONFIG_FIELDSETS contains extra field(s) that does not exist in CONFIG.'), - hint=', '.join(sorted(extra_keys)), - obj='settings.CONSTANCE_CONFIG', - id='constance.E002', + _("CONSTANCE_CONFIG_FIELDSETS contains extra field(s) that does not exist in CONFIG."), + hint=", ".join(sorted(extra_keys)), + obj="settings.CONSTANCE_CONFIG", + id="constance.E002", ) errors.append(check) return errors @@ -53,8 +53,8 @@ def get_inconsistent_fieldnames() -> tuple[set, set]: for _fieldset_title, fields_list in fieldset_items: # fields_list can be a dictionary, when a fieldset is defined as collapsible # https://django-constance.readthedocs.io/en/latest/#fieldsets-collapsing - if isinstance(fields_list, dict) and 'fields' in fields_list: - fields_list = fields_list['fields'] + if isinstance(fields_list, dict) and "fields" in fields_list: + fields_list = fields_list["fields"] unique_field_names.update(fields_list) if not unique_field_names: return unique_field_names, unique_field_names diff --git a/constance/codecs.py b/constance/codecs.py index 9219a94..7804a62 100644 --- a/constance/codecs.py +++ b/constance/codecs.py @@ -14,7 +14,7 @@ from typing import TypeVar logger = logging.getLogger(__name__) -DEFAULT_DISCRIMINATOR = 'default' +DEFAULT_DISCRIMINATOR = "default" class JSONEncoder(json.JSONEncoder): @@ -24,11 +24,11 @@ class JSONEncoder(json.JSONEncoder): for discriminator, (t, _, encoder) in _codecs.items(): if isinstance(o, t): return _as(discriminator, encoder(o)) - raise TypeError(f'Object of type {o.__class__.__name__} is not JSON serializable') + raise TypeError(f"Object of type {o.__class__.__name__} is not JSON serializable") def _as(discriminator: str, v: Any) -> dict[str, Any]: - return {'__type__': discriminator, '__value__': v} + return {"__type__": discriminator, "__value__": v} def dumps(obj, _dumps=json.dumps, cls=JSONEncoder, default_kwargs=None, **kwargs): @@ -44,7 +44,7 @@ def loads(s, _loads=json.loads, *, first_level=True, **kwargs): """Deserialize json string to object.""" if first_level: return _loads(s, object_hook=object_hook, **kwargs) - if isinstance(s, dict) and '__type__' not in s and '__value__' not in s: + if isinstance(s, dict) and "__type__" not in s and "__value__" not in s: return {k: loads(v, first_level=False) for k, v in s.items()} if isinstance(s, list): return list(loads(v, first_level=False) for v in s) @@ -53,20 +53,20 @@ def loads(s, _loads=json.loads, *, first_level=True, **kwargs): def object_hook(o: dict) -> Any: """Hook function to perform custom deserialization.""" - if o.keys() == {'__type__', '__value__'}: - if o['__type__'] == DEFAULT_DISCRIMINATOR: - return o['__value__'] - codec = _codecs.get(o['__type__']) + if o.keys() == {"__type__", "__value__"}: + if o["__type__"] == DEFAULT_DISCRIMINATOR: + return o["__value__"] + codec = _codecs.get(o["__type__"]) if not codec: - raise ValueError(f'Unsupported type: {o["__type__"]}') - return codec[1](o['__value__']) - if '__type__' not in o and '__value__' not in o: + raise ValueError(f"Unsupported type: {o['__type__']}") + return codec[1](o["__value__"]) + if "__type__" not in o and "__value__" not in o: return o - logger.error('Cannot deserialize object: %s', o) - raise ValueError(f'Invalid object: {o}') + logger.error("Cannot deserialize object: %s", o) + raise ValueError(f"Invalid object: {o}") -T = TypeVar('T') +T = TypeVar("T") class Encoder(Protocol[T]): @@ -79,9 +79,9 @@ class Decoder(Protocol[T]): def register_type(t: type[T], discriminator: str, encoder: Encoder[T], decoder: Decoder[T]): if not discriminator: - raise ValueError('Discriminator must be specified') + raise ValueError("Discriminator must be specified") if _codecs.get(discriminator) or discriminator == DEFAULT_DISCRIMINATOR: - raise ValueError(f'Type with discriminator {discriminator} is already registered') + raise ValueError(f"Type with discriminator {discriminator} is already registered") _codecs[discriminator] = (t, decoder, encoder) @@ -90,12 +90,12 @@ _codecs: dict[str, tuple[type, Decoder, Encoder]] = {} def _register_default_types(): # NOTE: datetime should be registered before date, because datetime is also instance of date. - register_type(datetime, 'datetime', datetime.isoformat, datetime.fromisoformat) - register_type(date, 'date', lambda o: o.isoformat(), lambda o: datetime.fromisoformat(o).date()) - register_type(time, 'time', lambda o: o.isoformat(), time.fromisoformat) - register_type(Decimal, 'decimal', str, Decimal) - register_type(uuid.UUID, 'uuid', lambda o: o.hex, uuid.UUID) - register_type(timedelta, 'timedelta', lambda o: o.total_seconds(), lambda o: timedelta(seconds=o)) + register_type(datetime, "datetime", datetime.isoformat, datetime.fromisoformat) + register_type(date, "date", lambda o: o.isoformat(), lambda o: datetime.fromisoformat(o).date()) + register_type(time, "time", lambda o: o.isoformat(), time.fromisoformat) + register_type(Decimal, "decimal", str, Decimal) + register_type(uuid.UUID, "uuid", lambda o: o.hex, uuid.UUID) + register_type(timedelta, "timedelta", lambda o: o.total_seconds(), lambda o: timedelta(seconds=o)) _register_default_types() diff --git a/constance/context_processors.py b/constance/context_processors.py index ab8d922..3a3da33 100644 --- a/constance/context_processors.py +++ b/constance/context_processors.py @@ -12,4 +12,4 @@ def config(request): ) """ - return {'config': constance.config} + return {"config": constance.config} diff --git a/constance/forms.py b/constance/forms.py index 5d52755..321ab47 100644 --- a/constance/forms.py +++ b/constance/forms.py @@ -25,27 +25,27 @@ from .checks import get_inconsistent_fieldnames config = LazyConfig() -NUMERIC_WIDGET = forms.TextInput(attrs={'size': 10}) +NUMERIC_WIDGET = forms.TextInput(attrs={"size": 10}) -INTEGER_LIKE = (fields.IntegerField, {'widget': NUMERIC_WIDGET}) +INTEGER_LIKE = (fields.IntegerField, {"widget": NUMERIC_WIDGET}) STRING_LIKE = ( fields.CharField, { - 'widget': forms.Textarea(attrs={'rows': 3}), - 'required': False, + "widget": forms.Textarea(attrs={"rows": 3}), + "required": False, }, ) FIELDS = { - bool: (fields.BooleanField, {'required': False}), + bool: (fields.BooleanField, {"required": False}), int: INTEGER_LIKE, - Decimal: (fields.DecimalField, {'widget': NUMERIC_WIDGET}), + Decimal: (fields.DecimalField, {"widget": NUMERIC_WIDGET}), str: STRING_LIKE, - datetime: (fields.SplitDateTimeField, {'widget': widgets.AdminSplitDateTime}), - timedelta: (fields.DurationField, {'widget': widgets.AdminTextInputWidget}), - date: (fields.DateField, {'widget': widgets.AdminDateWidget}), - time: (fields.TimeField, {'widget': widgets.AdminTimeWidget}), - float: (fields.FloatField, {'widget': NUMERIC_WIDGET}), + datetime: (fields.SplitDateTimeField, {"widget": widgets.AdminSplitDateTime}), + timedelta: (fields.DurationField, {"widget": widgets.AdminTextInputWidget}), + date: (fields.DateField, {"widget": widgets.AdminDateWidget}), + time: (fields.TimeField, {"widget": widgets.AdminTimeWidget}), + float: (fields.FloatField, {"widget": NUMERIC_WIDGET}), } @@ -58,12 +58,12 @@ def parse_additional_fields(fields): field[0] = import_string(field[0]) - if 'widget' in field[1]: - klass = import_string(field[1]['widget']) - field[1]['widget'] = klass(**(field[1].get('widget_kwargs', {}) or {})) + if "widget" in field[1]: + klass = import_string(field[1]["widget"]) + field[1]["widget"] = klass(**(field[1].get("widget_kwargs", {}) or {})) - if 'widget_kwargs' in field[1]: - del field[1]['widget_kwargs'] + if "widget_kwargs" in field[1]: + del field[1]["widget_kwargs"] fields[key] = field @@ -80,7 +80,7 @@ class ConstanceForm(forms.Form): super().__init__(*args, initial=initial, **kwargs) version_hash = hashlib.sha256() - only_view = request and not request.user.has_perm('constance.change_config') + only_view = request and not request.user.has_perm("constance.change_config") if only_view: messages.warning( request, @@ -94,13 +94,13 @@ class ConstanceForm(forms.Form): if config_type not in settings.ADDITIONAL_FIELDS and not isinstance(default, config_type): raise ImproperlyConfigured( _( - 'Default value type must be ' - 'equal to declared config ' - 'parameter type. Please fix ' - 'the default value of ' + "Default value type must be " + "equal to declared config " + "parameter type. Please fix " + "the default value of " "'%(name)s'." ) - % {'name': name} + % {"name": name} ) else: config_type = type(default) @@ -109,19 +109,19 @@ class ConstanceForm(forms.Form): raise ImproperlyConfigured( _( "Constance doesn't support " - 'config values of the type ' - '%(config_type)s. Please fix ' + "config values of the type " + "%(config_type)s. Please fix " "the value of '%(name)s'." ) - % {'config_type': config_type, 'name': name} + % {"config_type": config_type, "name": name} ) field_class, kwargs = FIELDS[config_type] if only_view: - kwargs['disabled'] = True + kwargs["disabled"] = True self.fields[name] = field_class(label=name, **kwargs) - version_hash.update(smart_bytes(initial.get(name, ''))) - self.initial['version'] = version_hash.hexdigest() + version_hash.update(smart_bytes(initial.get(name, ""))) + self.initial["version"] = version_hash.hexdigest() def save(self): for file_field in self.files: @@ -142,14 +142,14 @@ class ConstanceForm(forms.Form): setattr(config, name, new) def clean_version(self): - value = self.cleaned_data['version'] + value = self.cleaned_data["version"] if settings.IGNORE_ADMIN_VERSION_CHECK: return value - if value != self.initial['version']: + if value != self.initial["version"]: raise forms.ValidationError( - _('The settings have been modified by someone else. Please reload the form and resubmit your changes.') + _("The settings have been modified by someone else. Please reload the form and resubmit your changes.") ) return value @@ -162,7 +162,7 @@ class ConstanceForm(forms.Form): missing_keys, extra_keys = get_inconsistent_fieldnames() if missing_keys or extra_keys: raise forms.ValidationError( - _('CONSTANCE_CONFIG_FIELDSETS is missing field(s) that exists in CONSTANCE_CONFIG.') + _("CONSTANCE_CONFIG_FIELDSETS is missing field(s) that exists in CONSTANCE_CONFIG.") ) return cleaned_data diff --git a/constance/management/commands/constance.py b/constance/management/commands/constance.py index 289b459..9af50b4 100644 --- a/constance/management/commands/constance.py +++ b/constance/management/commands/constance.py @@ -26,36 +26,36 @@ def _set_constance_value(key, value): class Command(BaseCommand): - help = _('Get/Set In-database config settings handled by Constance') + help = _("Get/Set In-database config settings handled by Constance") - GET = 'get' - SET = 'set' - LIST = 'list' - REMOVE_STALE_KEYS = 'remove_stale_keys' + GET = "get" + SET = "set" + LIST = "list" + REMOVE_STALE_KEYS = "remove_stale_keys" def add_arguments(self, parser): - subparsers = parser.add_subparsers(dest='command') - subparsers.add_parser(self.LIST, help='list all Constance keys and their values') + subparsers = parser.add_subparsers(dest="command") + subparsers.add_parser(self.LIST, help="list all Constance keys and their values") - parser_get = subparsers.add_parser(self.GET, help='get the value of a Constance key') - parser_get.add_argument('key', help='name of the key to get', metavar='KEY') + parser_get = subparsers.add_parser(self.GET, help="get the value of a Constance key") + parser_get.add_argument("key", help="name of the key to get", metavar="KEY") - parser_set = subparsers.add_parser(self.SET, help='set the value of a Constance key') - parser_set.add_argument('key', help='name of the key to set', metavar='KEY') + parser_set = subparsers.add_parser(self.SET, help="set the value of a Constance key") + parser_set.add_argument("key", help="name of the key to set", metavar="KEY") # use nargs='+' so that we pass a list to MultiValueField (eg SplitDateTimeField) - parser_set.add_argument('value', help='value to set', metavar='VALUE', nargs='+') + parser_set.add_argument("value", help="value to set", metavar="VALUE", nargs="+") subparsers.add_parser( self.REMOVE_STALE_KEYS, - help='delete all Constance keys and their values if they are not in settings.CONSTANCE_CONFIG (stale keys)', + help="delete all Constance keys and their values if they are not in settings.CONSTANCE_CONFIG (stale keys)", ) def handle(self, command, key=None, value=None, *args, **options): if command == self.GET: try: - self.stdout.write(str(getattr(config, key)), ending='\n') + self.stdout.write(str(getattr(config, key)), ending="\n") except AttributeError as e: - raise CommandError(f'{key} is not defined in settings.CONSTANCE_CONFIG') from e + raise CommandError(f"{key} is not defined in settings.CONSTANCE_CONFIG") from e elif command == self.SET: try: if len(value) == 1: @@ -63,21 +63,21 @@ class Command(BaseCommand): value = value[0] _set_constance_value(key, value) except KeyError as e: - raise CommandError(f'{key} is not defined in settings.CONSTANCE_CONFIG') from e + raise CommandError(f"{key} is not defined in settings.CONSTANCE_CONFIG") from e except ValidationError as e: - raise CommandError(', '.join(e)) from e + raise CommandError(", ".join(e)) from e elif command == self.LIST: for k, v in get_values().items(): - self.stdout.write(f'{k}\t{v}', ending='\n') + self.stdout.write(f"{k}\t{v}", ending="\n") elif command == self.REMOVE_STALE_KEYS: actual_keys = settings.CONSTANCE_CONFIG.keys() stale_records = Constance.objects.exclude(key__in=actual_keys) if stale_records: - self.stdout.write('The following record will be deleted:', ending='\n') + self.stdout.write("The following record will be deleted:", ending="\n") else: - self.stdout.write('There are no stale records in the database.', ending='\n') + self.stdout.write("There are no stale records in the database.", ending="\n") for stale_record in stale_records: - self.stdout.write(f'{stale_record.key}\t{stale_record.value}', ending='\n') + self.stdout.write(f"{stale_record.key}\t{stale_record.value}", ending="\n") stale_records.delete() else: - raise CommandError('Invalid command') + raise CommandError("Invalid command") diff --git a/constance/migrations/0001_initial.py b/constance/migrations/0001_initial.py index f1e187a..6f3e663 100644 --- a/constance/migrations/0001_initial.py +++ b/constance/migrations/0001_initial.py @@ -9,16 +9,16 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Constance', + name="Constance", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('key', models.CharField(max_length=255, unique=True)), - ('value', models.TextField(blank=True, editable=False, null=True)), + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("key", models.CharField(max_length=255, unique=True)), + ("value", models.TextField(blank=True, editable=False, null=True)), ], options={ - 'verbose_name': 'constance', - 'verbose_name_plural': 'constances', - 'permissions': [('change_config', 'Can change config'), ('view_config', 'Can view config')], + "verbose_name": "constance", + "verbose_name_plural": "constances", + "permissions": [("change_config", "Can change config"), ("view_config", "Can view config")], }, ), ] diff --git a/constance/migrations/0002_migrate_from_old_table.py b/constance/migrations/0002_migrate_from_old_table.py index 9e88284..f4aee78 100644 --- a/constance/migrations/0002_migrate_from_old_table.py +++ b/constance/migrations/0002_migrate_from_old_table.py @@ -12,19 +12,19 @@ def _migrate_from_old_table(apps, schema_editor) -> None: On new installations just ignore error that table does not exist. """ connection = schema_editor.connection - quoted_string = ', '.join([connection.ops.quote_name(item) for item in ['id', 'key', 'value']]) - old_table_name = 'constance_config' + quoted_string = ", ".join([connection.ops.quote_name(item) for item in ["id", "key", "value"]]) + old_table_name = "constance_config" with connection.cursor() as cursor: if old_table_name not in connection.introspection.table_names(): - logger.info('Old table does not exist, skipping') + logger.info("Old table does not exist, skipping") return cursor.execute( - f'INSERT INTO constance_constance ( {quoted_string} ) SELECT {quoted_string} FROM {old_table_name}', # noqa: S608 + f"INSERT INTO constance_constance ( {quoted_string} ) SELECT {quoted_string} FROM {old_table_name}", # noqa: S608 [], ) - cursor.execute(f'DROP TABLE {old_table_name}', []) + cursor.execute(f"DROP TABLE {old_table_name}", []) - Constance = apps.get_model('constance', 'Constance') + Constance = apps.get_model("constance", "Constance") sequence_sql = connection.ops.sequence_reset_sql(no_style(), [Constance]) with connection.cursor() as cursor: for sql in sequence_sql: @@ -32,7 +32,7 @@ def _migrate_from_old_table(apps, schema_editor) -> None: class Migration(migrations.Migration): - dependencies = [('constance', '0001_initial')] + dependencies = [("constance", "0001_initial")] atomic = False diff --git a/constance/migrations/0003_drop_pickle.py b/constance/migrations/0003_drop_pickle.py index fdfc15b..d64dcb0 100644 --- a/constance/migrations/0003_drop_pickle.py +++ b/constance/migrations/0003_drop_pickle.py @@ -15,7 +15,7 @@ logger = logging.getLogger(__name__) def is_already_migrated(value): try: data = json.loads(value) - if isinstance(data, dict) and set(data.keys()) == {'__type__', '__value__'}: + if isinstance(data, dict) and set(data.keys()) == {"__type__", "__value__"}: return True except (json.JSONDecodeError, TypeError, UnicodeDecodeError): return False @@ -23,21 +23,21 @@ def is_already_migrated(value): def import_module_attr(path): - package, module = path.rsplit('.', 1) + package, module = path.rsplit(".", 1) return getattr(import_module(package), module) def migrate_pickled_data(apps, schema_editor) -> None: # pragma: no cover - Constance = apps.get_model('constance', 'Constance') + Constance = apps.get_model("constance", "Constance") for constance in Constance.objects.exclude(value=None): if not is_already_migrated(constance.value): constance.value = dumps(pickle.loads(b64decode(constance.value.encode()))) # noqa: S301 - constance.save(update_fields=['value']) + constance.save(update_fields=["value"]) if settings.BACKEND in ( - 'constance.backends.redisd.RedisBackend', - 'constance.backends.redisd.CachingRedisBackend', + "constance.backends.redisd.RedisBackend", + "constance.backends.redisd.CachingRedisBackend", ): import redis @@ -52,7 +52,7 @@ def migrate_pickled_data(apps, schema_editor) -> None: # pragma: no cover _rd = redis.Redis(**settings.REDIS_CONNECTION) redis_migrated_data = {} for key in settings.CONFIG: - prefixed_key = f'{_prefix}{key}' + prefixed_key = f"{_prefix}{key}" value = _rd.get(prefixed_key) if value is not None and not is_already_migrated(value): redis_migrated_data[prefixed_key] = dumps(pickle.loads(value)) # noqa: S301 @@ -61,7 +61,7 @@ def migrate_pickled_data(apps, schema_editor) -> None: # pragma: no cover class Migration(migrations.Migration): - dependencies = [('constance', '0002_migrate_from_old_table')] + dependencies = [("constance", "0002_migrate_from_old_table")] operations = [ migrations.RunPython(migrate_pickled_data), diff --git a/constance/models.py b/constance/models.py index 49213b4..be4ffc4 100644 --- a/constance/models.py +++ b/constance/models.py @@ -7,11 +7,11 @@ class Constance(models.Model): value = models.TextField(null=True, blank=True, editable=False) class Meta: - verbose_name = _('constance') - verbose_name_plural = _('constances') + verbose_name = _("constance") + verbose_name_plural = _("constances") permissions = [ - ('change_config', 'Can change config'), - ('view_config', 'Can view config'), + ("change_config", "Can change config"), + ("view_config", "Can view config"), ] def __str__(self): diff --git a/constance/settings.py b/constance/settings.py index fd8045c..988ca84 100644 --- a/constance/settings.py +++ b/constance/settings.py @@ -1,29 +1,29 @@ from django.conf import settings -BACKEND = getattr(settings, 'CONSTANCE_BACKEND', 'constance.backends.redisd.RedisBackend') +BACKEND = getattr(settings, "CONSTANCE_BACKEND", "constance.backends.redisd.RedisBackend") -CONFIG = getattr(settings, 'CONSTANCE_CONFIG', {}) +CONFIG = getattr(settings, "CONSTANCE_CONFIG", {}) -CONFIG_FIELDSETS = getattr(settings, 'CONSTANCE_CONFIG_FIELDSETS', {}) +CONFIG_FIELDSETS = getattr(settings, "CONSTANCE_CONFIG_FIELDSETS", {}) -ADDITIONAL_FIELDS = getattr(settings, 'CONSTANCE_ADDITIONAL_FIELDS', {}) +ADDITIONAL_FIELDS = getattr(settings, "CONSTANCE_ADDITIONAL_FIELDS", {}) -FILE_ROOT = getattr(settings, 'CONSTANCE_FILE_ROOT', '') +FILE_ROOT = getattr(settings, "CONSTANCE_FILE_ROOT", "") -DATABASE_CACHE_BACKEND = getattr(settings, 'CONSTANCE_DATABASE_CACHE_BACKEND', None) +DATABASE_CACHE_BACKEND = getattr(settings, "CONSTANCE_DATABASE_CACHE_BACKEND", None) -DATABASE_CACHE_AUTOFILL_TIMEOUT = getattr(settings, 'CONSTANCE_DATABASE_CACHE_AUTOFILL_TIMEOUT', 60 * 60 * 24) +DATABASE_CACHE_AUTOFILL_TIMEOUT = getattr(settings, "CONSTANCE_DATABASE_CACHE_AUTOFILL_TIMEOUT", 60 * 60 * 24) -DATABASE_PREFIX = getattr(settings, 'CONSTANCE_DATABASE_PREFIX', '') +DATABASE_PREFIX = getattr(settings, "CONSTANCE_DATABASE_PREFIX", "") -REDIS_PREFIX = getattr(settings, 'CONSTANCE_REDIS_PREFIX', 'constance:') +REDIS_PREFIX = getattr(settings, "CONSTANCE_REDIS_PREFIX", "constance:") -REDIS_CACHE_TIMEOUT = getattr(settings, 'CONSTANCE_REDIS_CACHE_TIMEOUT', 60) +REDIS_CACHE_TIMEOUT = getattr(settings, "CONSTANCE_REDIS_CACHE_TIMEOUT", 60) -REDIS_CONNECTION_CLASS = getattr(settings, 'CONSTANCE_REDIS_CONNECTION_CLASS', None) +REDIS_CONNECTION_CLASS = getattr(settings, "CONSTANCE_REDIS_CONNECTION_CLASS", None) -REDIS_CONNECTION = getattr(settings, 'CONSTANCE_REDIS_CONNECTION', {}) +REDIS_CONNECTION = getattr(settings, "CONSTANCE_REDIS_CONNECTION", {}) -SUPERUSER_ONLY = getattr(settings, 'CONSTANCE_SUPERUSER_ONLY', True) +SUPERUSER_ONLY = getattr(settings, "CONSTANCE_SUPERUSER_ONLY", True) -IGNORE_ADMIN_VERSION_CHECK = getattr(settings, 'CONSTANCE_IGNORE_ADMIN_VERSION_CHECK', False) +IGNORE_ADMIN_VERSION_CHECK = getattr(settings, "CONSTANCE_IGNORE_ADMIN_VERSION_CHECK", False) diff --git a/constance/test/__init__.py b/constance/test/__init__.py index 9c1a2bb..2679500 100644 --- a/constance/test/__init__.py +++ b/constance/test/__init__.py @@ -1,3 +1,3 @@ from .unittest import override_config # pragma: no cover -__all__ = ['override_config'] +__all__ = ["override_config"] diff --git a/constance/test/pytest.py b/constance/test/pytest.py index cd3f8b5..651ec83 100644 --- a/constance/test/pytest.py +++ b/constance/test/pytest.py @@ -14,16 +14,16 @@ from constance import config as constance_config @pytest.hookimpl(trylast=True) def pytest_configure(config): # pragma: no cover """Register override_config marker.""" - config.addinivalue_line('markers', ('override_config(**kwargs): mark test to override django-constance config')) + config.addinivalue_line("markers", ("override_config(**kwargs): mark test to override django-constance config")) @pytest.hookimpl(hookwrapper=True) def pytest_runtest_call(item): # pragma: no cover """Validate constance override marker params. Run test with overridden config.""" - marker = item.get_closest_marker('override_config') + marker = item.get_closest_marker("override_config") if marker is not None: if marker.args: - pytest.fail('Constance override can not not accept positional args') + pytest.fail("Constance override can not not accept positional args") with override_config(**marker.kwargs): yield else: @@ -59,7 +59,7 @@ class override_config(ContextDecorator): self.disable() -@pytest.fixture(name='override_config') +@pytest.fixture(name="override_config") def _override_config(): """Make override_config available as a function fixture.""" return override_config diff --git a/constance/test/unittest.py b/constance/test/unittest.py index 510aab0..779300c 100644 --- a/constance/test/unittest.py +++ b/constance/test/unittest.py @@ -6,7 +6,7 @@ from django.test.utils import override_settings from constance import config -__all__ = ('override_config',) +__all__ = ("override_config",) class override_config(override_settings): @@ -24,7 +24,7 @@ class override_config(override_settings): """Modify the decorated function to override config values.""" if isinstance(test_func, type): if not issubclass(test_func, SimpleTestCase): - raise Exception('Only subclasses of Django SimpleTestCase can be decorated with override_config') + raise Exception("Only subclasses of Django SimpleTestCase can be decorated with override_config") return self.modify_test_case(test_func) @wraps(test_func) diff --git a/constance/utils.py b/constance/utils.py index e3ec12c..87dfe85 100644 --- a/constance/utils.py +++ b/constance/utils.py @@ -7,7 +7,7 @@ config = LazyConfig() def import_module_attr(path): - package, module = path.rsplit('.', 1) + package, module = path.rsplit(".", 1) return getattr(import_module(package), module) @@ -31,7 +31,7 @@ def get_values_for_keys(keys): :raises AttributeError: If any key is not found in the configuration. """ if not isinstance(keys, (list, tuple, set)): - raise TypeError('keys must be a list, tuple, or set of strings') + raise TypeError("keys must be a list, tuple, or set of strings") # Prepare default initial mapping default_initial = {name: options[0] for name, options in settings.CONFIG.items() if name in keys} diff --git a/docs/conf.py b/docs/conf.py index 467a8bb..3526dd1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,56 +10,56 @@ from datetime import datetime def get_version(): - with open('../pyproject.toml') as f: + with open("../pyproject.toml") as f: for line in f: match = re.match(r'version = "(.*)"', line) if match: return match.group(1) - return '0.0.0' + return "0.0.0" -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tests.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings") # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('extensions')) -sys.path.insert(0, os.path.abspath('..')) +sys.path.insert(0, os.path.abspath("extensions")) +sys.path.insert(0, os.path.abspath("..")) # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = 'django-constance' -project_copyright = datetime.now().year.__str__() + ', Jazzband' +project = "django-constance" +project_copyright = datetime.now().year.__str__() + ", Jazzband" # The full version, including alpha/beta/rc tags release = get_version() # The short X.Y version -version = '.'.join(release.split('.')[:3]) +version = ".".join(release.split(".")[:3]) # -- General configuration ------------------------------------------------ # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx_search.extension', - 'settings', + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx_search.extension", + "settings", ] -templates_path = ['_templates'] -source_suffix = '.rst' -root_doc = 'index' -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] -pygments_style = 'sphinx' -html_last_updated_fmt = '' +templates_path = ["_templates"] +source_suffix = ".rst" +root_doc = "index" +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +pygments_style = "sphinx" +html_last_updated_fmt = "" # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -html_theme = 'sphinx_rtd_theme' -html_static_path = ['_static'] -htmlhelp_basename = 'django-constancedoc' +html_theme = "sphinx_rtd_theme" +html_static_path = ["_static"] +htmlhelp_basename = "django-constancedoc" # -- Options for LaTeX output --------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-latex-output @@ -67,31 +67,31 @@ htmlhelp_basename = 'django-constancedoc' latex_elements = {} latex_documents = [ - ('index', 'django-constance.tex', 'django-constance Documentation', 'Jazzband', 'manual'), + ("index", "django-constance.tex", "django-constance Documentation", "Jazzband", "manual"), ] # -- Options for manual page output --------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-manual-page-output -man_pages = [('index', 'django-constance', 'django-constance Documentation', ['Jazzband'], 1)] +man_pages = [("index", "django-constance", "django-constance Documentation", ["Jazzband"], 1)] # -- Options for Texinfo output ------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-texinfo-output texinfo_documents = [ ( - 'index', - 'django-constance', - 'django-constance Documentation', - 'Jazzband', - 'django-constance', - 'One line description of project.', - 'Miscellaneous', + "index", + "django-constance", + "django-constance Documentation", + "Jazzband", + "django-constance", + "One line description of project.", + "Miscellaneous", ), ] # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { - 'python': ('https://docs.python.org/3', None), - 'django': ('https://docs.djangoproject.com/en/dev/', 'https://docs.djangoproject.com/en/dev/_objects/'), + "python": ("https://docs.python.org/3", None), + "django": ("https://docs.djangoproject.com/en/dev/", "https://docs.djangoproject.com/en/dev/_objects/"), } diff --git a/docs/extensions/settings.py b/docs/extensions/settings.py index 7cf389a..2551233 100644 --- a/docs/extensions/settings.py +++ b/docs/extensions/settings.py @@ -1,6 +1,6 @@ def setup(app): app.add_crossref_type( - directivename='setting', - rolename='setting', - indextemplate='pair: %s; setting', + directivename="setting", + rolename="setting", + indextemplate="pair: %s; setting", ) diff --git a/example/cheeseshop/apps/catalog/migrations/0001_initial.py b/example/cheeseshop/apps/catalog/migrations/0001_initial.py index cfbae89..2a6ac9d 100644 --- a/example/cheeseshop/apps/catalog/migrations/0001_initial.py +++ b/example/cheeseshop/apps/catalog/migrations/0001_initial.py @@ -7,10 +7,10 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Brand', + name="Brand", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=75)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("name", models.CharField(max_length=75)), ], ), ] diff --git a/example/cheeseshop/apps/storage/migrations/0001_initial.py b/example/cheeseshop/apps/storage/migrations/0001_initial.py index f5970be..5b240aa 100644 --- a/example/cheeseshop/apps/storage/migrations/0001_initial.py +++ b/example/cheeseshop/apps/storage/migrations/0001_initial.py @@ -7,23 +7,23 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Shelf', + name="Shelf", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=75)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("name", models.CharField(max_length=75)), ], options={ - 'verbose_name_plural': 'shelves', + "verbose_name_plural": "shelves", }, ), migrations.CreateModel( - name='Supply', + name="Supply", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=75)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("name", models.CharField(max_length=75)), ], options={ - 'verbose_name_plural': 'supplies', + "verbose_name_plural": "supplies", }, ), ] diff --git a/example/cheeseshop/apps/storage/models.py b/example/cheeseshop/apps/storage/models.py index 367a9c1..2271795 100644 --- a/example/cheeseshop/apps/storage/models.py +++ b/example/cheeseshop/apps/storage/models.py @@ -5,11 +5,11 @@ class Shelf(models.Model): name = models.CharField(max_length=75) class Meta: - verbose_name_plural = 'shelves' + verbose_name_plural = "shelves" class Supply(models.Model): name = models.CharField(max_length=75) class Meta: - verbose_name_plural = 'supplies' + verbose_name_plural = "supplies" diff --git a/example/cheeseshop/fields.py b/example/cheeseshop/fields.py index e6fc8be..9c02923 100644 --- a/example/cheeseshop/fields.py +++ b/example/cheeseshop/fields.py @@ -13,7 +13,7 @@ class JsonField(fields.CharField): def widget_attrs(self, widget: widgets.Widget): attrs = super().widget_attrs(widget) - attrs['rows'] = self.rows + attrs["rows"] = self.rows return attrs def to_python(self, value): diff --git a/example/cheeseshop/settings.py b/example/cheeseshop/settings.py index 75bc6b2..44fdbed 100644 --- a/example/cheeseshop/settings.py +++ b/example/cheeseshop/settings.py @@ -21,7 +21,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SITE_ID = 1 # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'hdx64#m+lnc_0ffoyehbk&7gk1&*9uar$pcfcm-%$km#p0$k=6' +SECRET_KEY = "hdx64#m+lnc_0ffoyehbk&7gk1&*9uar$pcfcm-%$km#p0$k=6" # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -32,122 +32,122 @@ ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'cheeseshop.apps.catalog', - 'cheeseshop.apps.storage', - 'constance', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + "cheeseshop.apps.catalog", + "cheeseshop.apps.storage", + "constance", ) MIDDLEWARE = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', + "django.middleware.common.CommonMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", ) -ROOT_URLCONF = 'cheeseshop.urls' +ROOT_URLCONF = "cheeseshop.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", ], }, }, ] -WSGI_APPLICATION = 'cheeseshop.wsgi.application' +WSGI_APPLICATION = "cheeseshop.wsgi.application" # Database # https://docs.djangoproject.com/en/4.1/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': '/tmp/cheeseshop.db', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "/tmp/cheeseshop.db", } } CONSTANCE_REDIS_CONNECTION = { - 'host': 'localhost', - 'port': 6379, - 'db': 0, + "host": "localhost", + "port": 6379, + "db": 0, } CONSTANCE_ADDITIONAL_FIELDS = { - 'yes_no_null_select': [ - 'django.forms.fields.ChoiceField', - {'widget': 'django.forms.Select', 'choices': ((None, '-----'), ('yes', 'Yes'), ('no', 'No'))}, + "yes_no_null_select": [ + "django.forms.fields.ChoiceField", + {"widget": "django.forms.Select", "choices": ((None, "-----"), ("yes", "Yes"), ("no", "No"))}, ], - 'email': ('django.forms.fields.EmailField',), - 'json_field': ['cheeseshop.fields.JsonField'], - 'image_field': ['django.forms.ImageField', {}], + "email": ("django.forms.fields.EmailField",), + "json_field": ["cheeseshop.fields.JsonField"], + "image_field": ["django.forms.ImageField", {}], } CONSTANCE_CONFIG = { - 'BANNER': ('The National Cheese Emporium', 'name of the shop'), - 'OWNER': ('Mr. Henry Wensleydale', 'owner of the shop'), - 'OWNER_EMAIL': ('henry@example.com', 'contact email for owner', 'email'), - 'MUSICIANS': (4, 'number of musicians inside the shop'), - 'DATE_ESTABLISHED': (date(1972, 11, 30), "the shop's first opening"), - 'MY_SELECT_KEY': ('yes', 'select yes or no', 'yes_no_null_select'), - 'MULTILINE': ('Line one\nLine two', 'multiline string'), - 'JSON_DATA': ( - {'a': 1_000, 'b': 'test', 'max': 30_000_000}, - 'Some test data for json', - 'json_field', + "BANNER": ("The National Cheese Emporium", "name of the shop"), + "OWNER": ("Mr. Henry Wensleydale", "owner of the shop"), + "OWNER_EMAIL": ("henry@example.com", "contact email for owner", "email"), + "MUSICIANS": (4, "number of musicians inside the shop"), + "DATE_ESTABLISHED": (date(1972, 11, 30), "the shop's first opening"), + "MY_SELECT_KEY": ("yes", "select yes or no", "yes_no_null_select"), + "MULTILINE": ("Line one\nLine two", "multiline string"), + "JSON_DATA": ( + {"a": 1_000, "b": "test", "max": 30_000_000}, + "Some test data for json", + "json_field", ), - 'LOGO': ( - '', - 'Logo image file', - 'image_field', + "LOGO": ( + "", + "Logo image file", + "image_field", ), } CONSTANCE_CONFIG_FIELDSETS = { - 'Cheese shop general info': [ - 'BANNER', - 'OWNER', - 'OWNER_EMAIL', - 'MUSICIANS', - 'DATE_ESTABLISHED', - 'LOGO', + "Cheese shop general info": [ + "BANNER", + "OWNER", + "OWNER_EMAIL", + "MUSICIANS", + "DATE_ESTABLISHED", + "LOGO", ], - 'Awkward test settings': ['MY_SELECT_KEY', 'MULTILINE', 'JSON_DATA'], + "Awkward test settings": ["MY_SELECT_KEY", "MULTILINE", "JSON_DATA"], } -CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend' +CONSTANCE_BACKEND = "constance.backends.database.DatabaseBackend" CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache', - 'LOCATION': '127.0.0.1:11211', + "default": { + "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache", + "LOCATION": "127.0.0.1:11211", } } -CONSTANCE_DATABASE_CACHE_BACKEND = 'default' +CONSTANCE_DATABASE_CACHE_BACKEND = "default" # Internationalization # https://docs.djangoproject.com/en/4.1/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" -TIME_ZONE = 'America/Chicago' +TIME_ZONE = "America/Chicago" USE_I18N = True @@ -159,12 +159,12 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ -STATIC_URL = '/static/' +STATIC_URL = "/static/" -MEDIA_URL = '/media/' +MEDIA_URL = "/media/" -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_ROOT = os.path.join(BASE_DIR, "media") -CONSTANCE_FILE_ROOT = 'constance' +CONSTANCE_FILE_ROOT = "constance" -DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" diff --git a/example/cheeseshop/urls.py b/example/cheeseshop/urls.py index 7b68c4b..6ffc7b0 100644 --- a/example/cheeseshop/urls.py +++ b/example/cheeseshop/urls.py @@ -6,7 +6,7 @@ from django.urls import re_path admin.autodiscover() urlpatterns = [ - re_path('admin/', admin.site.urls), + re_path("admin/", admin.site.urls), ] if settings.DEBUG: diff --git a/example/cheeseshop/wsgi.py b/example/cheeseshop/wsgi.py index ce3dc33..96a17c4 100644 --- a/example/cheeseshop/wsgi.py +++ b/example/cheeseshop/wsgi.py @@ -2,6 +2,6 @@ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cheeseshop.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cheeseshop.settings") application = get_wsgi_application() diff --git a/example/manage.py b/example/manage.py index 81f8fe5..0ea7766 100755 --- a/example/manage.py +++ b/example/manage.py @@ -2,8 +2,8 @@ import os import sys -if __name__ == '__main__': - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cheeseshop.settings') +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cheeseshop.settings") from django.core.management import execute_from_command_line diff --git a/pyproject.toml b/pyproject.toml index 4238492..cc8effa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,6 @@ line-length = 120 indent-width = 4 [tool.ruff.format] -quote-style = "single" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto" diff --git a/tests/backends/test_database.py b/tests/backends/test_database.py index 16220a2..0401e65 100644 --- a/tests/backends/test_database.py +++ b/tests/backends/test_database.py @@ -7,7 +7,7 @@ from tests.storage import StorageTestsMixin class TestDatabase(StorageTestsMixin, TestCase): def setUp(self): self.old_backend = settings.BACKEND - settings.BACKEND = 'constance.backends.database.DatabaseBackend' + settings.BACKEND = "constance.backends.database.DatabaseBackend" super().setUp() def test_database_queries(self): diff --git a/tests/backends/test_memory.py b/tests/backends/test_memory.py index 6873556..0895c36 100644 --- a/tests/backends/test_memory.py +++ b/tests/backends/test_memory.py @@ -7,7 +7,7 @@ from tests.storage import StorageTestsMixin class TestMemory(StorageTestsMixin, TestCase): def setUp(self): self.old_backend = settings.BACKEND - settings.BACKEND = 'constance.backends.memory.MemoryBackend' + settings.BACKEND = "constance.backends.memory.MemoryBackend" super().setUp() self.config._backend._storage = {} diff --git a/tests/backends/test_redis.py b/tests/backends/test_redis.py index 3d9426d..578fc83 100644 --- a/tests/backends/test_redis.py +++ b/tests/backends/test_redis.py @@ -5,7 +5,7 @@ from tests.storage import StorageTestsMixin class TestRedis(StorageTestsMixin, TestCase): - _BACKEND = 'constance.backends.redisd.RedisBackend' + _BACKEND = "constance.backends.redisd.RedisBackend" def setUp(self): self.old_backend = settings.BACKEND @@ -19,4 +19,4 @@ class TestRedis(StorageTestsMixin, TestCase): class TestCachingRedis(TestRedis): - _BACKEND = 'constance.backends.redisd.CachingRedisBackend' + _BACKEND = "constance.backends.redisd.CachingRedisBackend" diff --git a/tests/settings.py b/tests/settings.py index 2b5b7e0..61656ab 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -4,107 +4,107 @@ from datetime import time from datetime import timedelta from decimal import Decimal -SECRET_KEY = 'cheese' +SECRET_KEY = "cheese" MIDDLEWARE = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.auth.middleware.SessionAuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ) -DATABASE_ENGINE = 'sqlite3' +DATABASE_ENGINE = "sqlite3" DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ':memory:', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ":memory:", }, - 'secondary': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ':memory:', + "secondary": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ":memory:", }, } INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.staticfiles', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'constance', - 'constance.backends.database', + "django.contrib.admin", + "django.contrib.staticfiles", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "constance", + "constance.backends.database", ) -ROOT_URLCONF = 'tests.urls' +ROOT_URLCONF = "tests.urls" -CONSTANCE_REDIS_CONNECTION_CLASS = 'tests.redis_mockup.Connection' +CONSTANCE_REDIS_CONNECTION_CLASS = "tests.redis_mockup.Connection" CONSTANCE_ADDITIONAL_FIELDS = { - 'yes_no_null_select': [ - 'django.forms.fields.ChoiceField', - {'widget': 'django.forms.Select', 'choices': ((None, '-----'), ('yes', 'Yes'), ('no', 'No'))}, + "yes_no_null_select": [ + "django.forms.fields.ChoiceField", + {"widget": "django.forms.Select", "choices": ((None, "-----"), ("yes", "Yes"), ("no", "No"))}, ], # note this intentionally uses a tuple so that we can test immutable - 'email': ('django.forms.fields.EmailField',), - 'array': ['django.forms.fields.CharField', {'widget': 'django.forms.Textarea'}], - 'json': ['django.forms.fields.CharField', {'widget': 'django.forms.Textarea'}], + "email": ("django.forms.fields.EmailField",), + "array": ["django.forms.fields.CharField", {"widget": "django.forms.Textarea"}], + "json": ["django.forms.fields.CharField", {"widget": "django.forms.Textarea"}], } USE_TZ = True CONSTANCE_CONFIG = { - 'INT_VALUE': (1, 'some int'), - 'BOOL_VALUE': (True, 'true or false'), - 'STRING_VALUE': ('Hello world', 'greetings'), - 'DECIMAL_VALUE': (Decimal('0.1'), 'the first release version'), - 'DATETIME_VALUE': (datetime(2010, 8, 23, 11, 29, 24), 'time of the first commit'), - 'FLOAT_VALUE': (3.1415926536, 'PI'), - 'DATE_VALUE': (date(2010, 12, 24), 'Merry Chrismas'), - 'TIME_VALUE': (time(23, 59, 59), 'And happy New Year'), - 'TIMEDELTA_VALUE': (timedelta(days=1, hours=2, minutes=3), 'Interval'), - 'CHOICE_VALUE': ('yes', 'select yes or no', 'yes_no_null_select'), - 'LINEBREAK_VALUE': ('Spam spam', 'eggs\neggs'), - 'EMAIL_VALUE': ('test@example.com', 'An email', 'email'), - 'LIST_VALUE': ([1, '1', date(2019, 1, 1)], 'A list', 'array'), - 'JSON_VALUE': ( + "INT_VALUE": (1, "some int"), + "BOOL_VALUE": (True, "true or false"), + "STRING_VALUE": ("Hello world", "greetings"), + "DECIMAL_VALUE": (Decimal("0.1"), "the first release version"), + "DATETIME_VALUE": (datetime(2010, 8, 23, 11, 29, 24), "time of the first commit"), + "FLOAT_VALUE": (3.1415926536, "PI"), + "DATE_VALUE": (date(2010, 12, 24), "Merry Chrismas"), + "TIME_VALUE": (time(23, 59, 59), "And happy New Year"), + "TIMEDELTA_VALUE": (timedelta(days=1, hours=2, minutes=3), "Interval"), + "CHOICE_VALUE": ("yes", "select yes or no", "yes_no_null_select"), + "LINEBREAK_VALUE": ("Spam spam", "eggs\neggs"), + "EMAIL_VALUE": ("test@example.com", "An email", "email"), + "LIST_VALUE": ([1, "1", date(2019, 1, 1)], "A list", "array"), + "JSON_VALUE": ( { - 'key': 'value', - 'key2': 2, - 'key3': [1, 2, 3], - 'key4': {'key': 'value'}, - 'key5': date(2019, 1, 1), - 'key6': None, + "key": "value", + "key2": 2, + "key3": [1, 2, 3], + "key4": {"key": "value"}, + "key5": date(2019, 1, 1), + "key6": None, }, - 'A JSON object', - 'json', + "A JSON object", + "json", ), } DEBUG = True -STATIC_ROOT = './static/' +STATIC_ROOT = "./static/" -STATIC_URL = '/static/' +STATIC_URL = "/static/" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.request', - 'django.template.context_processors.static', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - 'constance.context_processors.config', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.request", + "django.template.context_processors.static", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "constance.context_processors.config", ], }, }, diff --git a/tests/storage.py b/tests/storage.py index 13e7e99..932f252 100644 --- a/tests/storage.py +++ b/tests/storage.py @@ -16,60 +16,60 @@ class StorageTestsMixin: def test_store(self): self.assertEqual(self.config.INT_VALUE, 1) self.assertEqual(self.config.BOOL_VALUE, True) - self.assertEqual(self.config.STRING_VALUE, 'Hello world') - self.assertEqual(self.config.DECIMAL_VALUE, Decimal('0.1')) + self.assertEqual(self.config.STRING_VALUE, "Hello world") + self.assertEqual(self.config.DECIMAL_VALUE, Decimal("0.1")) self.assertEqual(self.config.DATETIME_VALUE, datetime(2010, 8, 23, 11, 29, 24)) self.assertEqual(self.config.FLOAT_VALUE, 3.1415926536) self.assertEqual(self.config.DATE_VALUE, date(2010, 12, 24)) self.assertEqual(self.config.TIME_VALUE, time(23, 59, 59)) self.assertEqual(self.config.TIMEDELTA_VALUE, timedelta(days=1, hours=2, minutes=3)) - self.assertEqual(self.config.CHOICE_VALUE, 'yes') - self.assertEqual(self.config.EMAIL_VALUE, 'test@example.com') - self.assertEqual(self.config.LIST_VALUE, [1, '1', date(2019, 1, 1)]) + self.assertEqual(self.config.CHOICE_VALUE, "yes") + self.assertEqual(self.config.EMAIL_VALUE, "test@example.com") + self.assertEqual(self.config.LIST_VALUE, [1, "1", date(2019, 1, 1)]) self.assertEqual( self.config.JSON_VALUE, { - 'key': 'value', - 'key2': 2, - 'key3': [1, 2, 3], - 'key4': {'key': 'value'}, - 'key5': date(2019, 1, 1), - 'key6': None, + "key": "value", + "key2": 2, + "key3": [1, 2, 3], + "key4": {"key": "value"}, + "key5": date(2019, 1, 1), + "key6": None, }, ) # set values self.config.INT_VALUE = 100 self.config.BOOL_VALUE = False - self.config.STRING_VALUE = 'Beware the weeping angel' - self.config.DECIMAL_VALUE = Decimal('1.2') + self.config.STRING_VALUE = "Beware the weeping angel" + self.config.DECIMAL_VALUE = Decimal("1.2") self.config.DATETIME_VALUE = datetime(1977, 10, 2) self.config.FLOAT_VALUE = 2.718281845905 self.config.DATE_VALUE = date(2001, 12, 20) self.config.TIME_VALUE = time(1, 59, 0) self.config.TIMEDELTA_VALUE = timedelta(days=2, hours=3, minutes=4) - self.config.CHOICE_VALUE = 'no' - self.config.EMAIL_VALUE = 'foo@bar.com' + self.config.CHOICE_VALUE = "no" + self.config.EMAIL_VALUE = "foo@bar.com" self.config.LIST_VALUE = [1, date(2020, 2, 2)] - self.config.JSON_VALUE = {'key': 'OK'} + self.config.JSON_VALUE = {"key": "OK"} # read again self.assertEqual(self.config.INT_VALUE, 100) self.assertEqual(self.config.BOOL_VALUE, False) - self.assertEqual(self.config.STRING_VALUE, 'Beware the weeping angel') - self.assertEqual(self.config.DECIMAL_VALUE, Decimal('1.2')) + self.assertEqual(self.config.STRING_VALUE, "Beware the weeping angel") + self.assertEqual(self.config.DECIMAL_VALUE, Decimal("1.2")) self.assertEqual(self.config.DATETIME_VALUE, datetime(1977, 10, 2)) self.assertEqual(self.config.FLOAT_VALUE, 2.718281845905) self.assertEqual(self.config.DATE_VALUE, date(2001, 12, 20)) self.assertEqual(self.config.TIME_VALUE, time(1, 59, 0)) self.assertEqual(self.config.TIMEDELTA_VALUE, timedelta(days=2, hours=3, minutes=4)) - self.assertEqual(self.config.CHOICE_VALUE, 'no') - self.assertEqual(self.config.EMAIL_VALUE, 'foo@bar.com') + self.assertEqual(self.config.CHOICE_VALUE, "no") + self.assertEqual(self.config.EMAIL_VALUE, "foo@bar.com") self.assertEqual(self.config.LIST_VALUE, [1, date(2020, 2, 2)]) - self.assertEqual(self.config.JSON_VALUE, {'key': 'OK'}) + self.assertEqual(self.config.JSON_VALUE, {"key": "OK"}) def test_nonexistent(self): - self.assertRaises(AttributeError, getattr, self.config, 'NON_EXISTENT') + self.assertRaises(AttributeError, getattr, self.config, "NON_EXISTENT") with self.assertRaises(AttributeError): self.config.NON_EXISTENT = 1 @@ -77,15 +77,15 @@ class StorageTestsMixin: def test_missing_values(self): # set some values and leave out others self.config.BOOL_VALUE = False - self.config.DECIMAL_VALUE = Decimal('1.2') + self.config.DECIMAL_VALUE = Decimal("1.2") self.config.DATETIME_VALUE = datetime(1977, 10, 2) self.config.DATE_VALUE = date(2001, 12, 20) self.config.TIME_VALUE = time(1, 59, 0) self.assertEqual(self.config.INT_VALUE, 1) # this should be the default value self.assertEqual(self.config.BOOL_VALUE, False) - self.assertEqual(self.config.STRING_VALUE, 'Hello world') # this should be the default value - self.assertEqual(self.config.DECIMAL_VALUE, Decimal('1.2')) + self.assertEqual(self.config.STRING_VALUE, "Hello world") # this should be the default value + self.assertEqual(self.config.DECIMAL_VALUE, Decimal("1.2")) self.assertEqual(self.config.DATETIME_VALUE, datetime(1977, 10, 2)) self.assertEqual(self.config.FLOAT_VALUE, 3.1415926536) # this should be the default value self.assertEqual(self.config.DATE_VALUE, date(2001, 12, 20)) @@ -96,12 +96,12 @@ class StorageTestsMixin: # Check corner cases such as falsy values self.config.INT_VALUE = 0 self.config.BOOL_VALUE = False - self.config.STRING_VALUE = '' + self.config.STRING_VALUE = "" values = dict(self.config._backend.mget(settings.CONFIG)) - self.assertEqual(values['INT_VALUE'], 0) - self.assertEqual(values['BOOL_VALUE'], False) - self.assertEqual(values['STRING_VALUE'], '') + self.assertEqual(values["INT_VALUE"], 0) + self.assertEqual(values["BOOL_VALUE"], False) + self.assertEqual(values["STRING_VALUE"], "") def test_backend_does_not_return_none_values(self): result = dict(self.config._backend.mget(settings.CONFIG)) diff --git a/tests/test_admin.py b/tests/test_admin.py index 91e6b6c..86666e3 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -23,196 +23,196 @@ class TestAdmin(TestCase): def setUp(self): super().setUp() self.rf = RequestFactory() - self.superuser = User.objects.create_superuser('admin', 'nimda', 'a@a.cz') - self.normaluser = User.objects.create_user('normal', 'nimda', 'b@b.cz') + self.superuser = User.objects.create_superuser("admin", "nimda", "a@a.cz") + self.normaluser = User.objects.create_user("normal", "nimda", "b@b.cz") self.normaluser.is_staff = True self.normaluser.save() self.options = admin.site._registry[self.model] def test_changelist(self): - self.client.login(username='admin', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="admin", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.superuser response = self.options.changelist_view(request, {}) self.assertEqual(response.status_code, 200) def test_custom_auth(self): settings.SUPERUSER_ONLY = False - self.client.login(username='normal', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="normal", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.normaluser self.assertRaises(PermissionDenied, self.options.changelist_view, request, {}) - self.assertFalse(request.user.has_perm('constance.change_config')) + self.assertFalse(request.user.has_perm("constance.change_config")) # reload user to reset permission cache - request = self.rf.get('/admin/constance/config/') + request = self.rf.get("/admin/constance/config/") request.user = User.objects.get(pk=self.normaluser.pk) - request.user.user_permissions.add(Permission.objects.get(codename='change_config')) - self.assertTrue(request.user.has_perm('constance.change_config')) + request.user.user_permissions.add(Permission.objects.get(codename="change_config")) + self.assertTrue(request.user.has_perm("constance.change_config")) response = self.options.changelist_view(request, {}) self.assertEqual(response.status_code, 200) def test_linebreaks(self): - self.client.login(username='admin', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="admin", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.superuser response = self.options.changelist_view(request, {}) - self.assertContains(response, 'LINEBREAK_VALUE') - self.assertContains(response, linebreaksbr('eggs\neggs')) + self.assertContains(response, "LINEBREAK_VALUE") + self.assertContains(response, linebreaksbr("eggs\neggs")) @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', + "constance.settings.CONFIG_FIELDSETS", { - 'Numbers': ('INT_VALUE',), - 'Text': ('STRING_VALUE',), + "Numbers": ("INT_VALUE",), + "Text": ("STRING_VALUE",), }, ) def test_fieldset_headers(self): - self.client.login(username='admin', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="admin", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.superuser response = self.options.changelist_view(request, {}) - self.assertContains(response, '

Numbers

') - self.assertContains(response, '

Text

') + self.assertContains(response, "

Numbers

") + self.assertContains(response, "

Text

") @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', + "constance.settings.CONFIG_FIELDSETS", ( - ('Numbers', ('INT_VALUE',)), - ('Text', ('STRING_VALUE',)), + ("Numbers", ("INT_VALUE",)), + ("Text", ("STRING_VALUE",)), ), ) def test_fieldset_tuple(self): - self.client.login(username='admin', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="admin", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.superuser response = self.options.changelist_view(request, {}) - self.assertContains(response, '

Numbers

') - self.assertContains(response, '

Text

') + self.assertContains(response, "

Numbers

") + self.assertContains(response, "

Text

") @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', + "constance.settings.CONFIG_FIELDSETS", { - 'Numbers': { - 'fields': ( - 'INT_VALUE', - 'DECIMAL_VALUE', + "Numbers": { + "fields": ( + "INT_VALUE", + "DECIMAL_VALUE", ), - 'collapse': True, + "collapse": True, }, - 'Text': { - 'fields': ( - 'STRING_VALUE', - 'LINEBREAK_VALUE', + "Text": { + "fields": ( + "STRING_VALUE", + "LINEBREAK_VALUE", ), - 'collapse': True, + "collapse": True, }, }, ) def test_collapsed_fieldsets(self): - self.client.login(username='admin', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="admin", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.superuser response = self.options.changelist_view(request, {}) - self.assertContains(response, 'module collapse') + self.assertContains(response, "module collapse") - @mock.patch('constance.settings.CONFIG_FIELDSETS', {'FieldSetOne': ('INT_VALUE',)}) + @mock.patch("constance.settings.CONFIG_FIELDSETS", {"FieldSetOne": ("INT_VALUE",)}) @mock.patch( - 'constance.settings.CONFIG', + "constance.settings.CONFIG", { - 'INT_VALUE': (1, 'some int'), + "INT_VALUE": (1, "some int"), }, ) - @mock.patch('constance.settings.IGNORE_ADMIN_VERSION_CHECK', True) - @mock.patch('constance.forms.ConstanceForm.save', lambda _: None) - @mock.patch('constance.forms.ConstanceForm.is_valid', lambda _: True) + @mock.patch("constance.settings.IGNORE_ADMIN_VERSION_CHECK", True) + @mock.patch("constance.forms.ConstanceForm.save", lambda _: None) + @mock.patch("constance.forms.ConstanceForm.is_valid", lambda _: True) def test_submit(self): """ Test that submitting the admin page results in an http redirect when everything is in order. """ - initial_value = {'INT_VALUE': settings.CONFIG['INT_VALUE'][0]} + initial_value = {"INT_VALUE": settings.CONFIG["INT_VALUE"][0]} - self.client.login(username='admin', password='nimda') + self.client.login(username="admin", password="nimda") request = self.rf.post( - '/admin/constance/config/', + "/admin/constance/config/", data={ **initial_value, - 'version': '123', + "version": "123", }, ) request.user = self.superuser request._dont_enforce_csrf_checks = True - with mock.patch('django.contrib.messages.add_message') as mock_message, mock.patch.object( - ConstanceForm, '__init__', **initial_value, return_value=None + with mock.patch("django.contrib.messages.add_message") as mock_message, mock.patch.object( + ConstanceForm, "__init__", **initial_value, return_value=None ) as mock_form: response = self.options.changelist_view(request, {}) mock_form.assert_called_with(data=request.POST, files=request.FILES, initial=initial_value, request=request) - mock_message.assert_called_with(request, 25, _('Live settings updated successfully.')) + mock_message.assert_called_with(request, 25, _("Live settings updated successfully.")) self.assertIsInstance(response, HttpResponseRedirect) - @mock.patch('constance.settings.CONFIG_FIELDSETS', {'FieldSetOne': ('MULTILINE',)}) + @mock.patch("constance.settings.CONFIG_FIELDSETS", {"FieldSetOne": ("MULTILINE",)}) @mock.patch( - 'constance.settings.CONFIG', + "constance.settings.CONFIG", { - 'MULTILINE': ('Hello\nWorld', 'multiline value'), + "MULTILINE": ("Hello\nWorld", "multiline value"), }, ) - @mock.patch('constance.settings.IGNORE_ADMIN_VERSION_CHECK', True) + @mock.patch("constance.settings.IGNORE_ADMIN_VERSION_CHECK", True) def test_newlines_normalization(self): - self.client.login(username='admin', password='nimda') + self.client.login(username="admin", password="nimda") request = self.rf.post( - '/admin/constance/config/', + "/admin/constance/config/", data={ - 'MULTILINE': 'Hello\r\nWorld', - 'version': '123', + "MULTILINE": "Hello\r\nWorld", + "version": "123", }, ) request.user = self.superuser request._dont_enforce_csrf_checks = True - with mock.patch('django.contrib.messages.add_message'): + with mock.patch("django.contrib.messages.add_message"): response = self.options.changelist_view(request, {}) self.assertIsInstance(response, HttpResponseRedirect) - self.assertEqual(get_values()['MULTILINE'], 'Hello\nWorld') + self.assertEqual(get_values()["MULTILINE"], "Hello\nWorld") @mock.patch( - 'constance.settings.CONFIG', + "constance.settings.CONFIG", { - 'DATETIME_VALUE': (datetime(2019, 8, 7, 18, 40, 0), 'some naive datetime'), + "DATETIME_VALUE": (datetime(2019, 8, 7, 18, 40, 0), "some naive datetime"), }, ) - @mock.patch('constance.settings.IGNORE_ADMIN_VERSION_CHECK', True) - @mock.patch('tests.redis_mockup.Connection.set', mock.MagicMock()) + @mock.patch("constance.settings.IGNORE_ADMIN_VERSION_CHECK", True) + @mock.patch("tests.redis_mockup.Connection.set", mock.MagicMock()) def test_submit_aware_datetime(self): """ Test that submitting the admin page results in an http redirect when everything is in order. """ request = self.rf.post( - '/admin/constance/config/', + "/admin/constance/config/", data={ - 'DATETIME_VALUE_0': '2019-08-07', - 'DATETIME_VALUE_1': '19:17:01', - 'version': '123', + "DATETIME_VALUE_0": "2019-08-07", + "DATETIME_VALUE_1": "19:17:01", + "version": "123", }, ) request.user = self.superuser request._dont_enforce_csrf_checks = True - with mock.patch('django.contrib.messages.add_message'): + with mock.patch("django.contrib.messages.add_message"): response = self.options.changelist_view(request, {}) self.assertIsInstance(response, HttpResponseRedirect) @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', + "constance.settings.CONFIG_FIELDSETS", { - 'Numbers': ('INT_VALUE',), - 'Text': ('STRING_VALUE',), + "Numbers": ("INT_VALUE",), + "Text": ("STRING_VALUE",), }, ) def test_inconsistent_fieldset_submit(self): @@ -220,51 +220,51 @@ class TestAdmin(TestCase): Test that the admin page warns users if the CONFIG_FIELDSETS setting doesn't account for every field in CONFIG. """ - self.client.login(username='admin', password='nimda') - request = self.rf.post('/admin/constance/config/', data=None) + self.client.login(username="admin", password="nimda") + request = self.rf.post("/admin/constance/config/", data=None) request.user = self.superuser request._dont_enforce_csrf_checks = True - with mock.patch('django.contrib.messages.add_message'): + with mock.patch("django.contrib.messages.add_message"): response = self.options.changelist_view(request, {}) - self.assertContains(response, 'is missing field(s)') + self.assertContains(response, "is missing field(s)") @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', + "constance.settings.CONFIG_FIELDSETS", { - 'Fieldsets': ( - 'STRING_VALUE', - 'INT_VALUE', + "Fieldsets": ( + "STRING_VALUE", + "INT_VALUE", ), }, ) def test_fieldset_ordering_1(self): """Ordering of inner list should be preserved.""" - self.client.login(username='admin', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="admin", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.superuser response = self.options.changelist_view(request, {}) response.render() content_str = response.content.decode() - self.assertGreater(content_str.find('INT_VALUE'), content_str.find('STRING_VALUE')) + self.assertGreater(content_str.find("INT_VALUE"), content_str.find("STRING_VALUE")) @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', + "constance.settings.CONFIG_FIELDSETS", { - 'Fieldsets': ( - 'INT_VALUE', - 'STRING_VALUE', + "Fieldsets": ( + "INT_VALUE", + "STRING_VALUE", ), }, ) def test_fieldset_ordering_2(self): """Ordering of inner list should be preserved.""" - self.client.login(username='admin', password='nimda') - request = self.rf.get('/admin/constance/config/') + self.client.login(username="admin", password="nimda") + request = self.rf.get("/admin/constance/config/") request.user = self.superuser response = self.options.changelist_view(request, {}) response.render() content_str = response.content.decode() - self.assertGreater(content_str.find('STRING_VALUE'), content_str.find('INT_VALUE')) + self.assertGreater(content_str.find("STRING_VALUE"), content_str.find("INT_VALUE")) def test_labels(self): self.assertEqual(type(self.model._meta.label), str) diff --git a/tests/test_checks.py b/tests/test_checks.py index 7880dfe..5bb98fb 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -8,7 +8,7 @@ from constance.checks import get_inconsistent_fieldnames class ChecksTestCase(TestCase): - @mock.patch('constance.settings.CONFIG_FIELDSETS', {'Set1': settings.CONFIG.keys()}) + @mock.patch("constance.settings.CONFIG_FIELDSETS", {"Set1": settings.CONFIG.keys()}) def test_get_inconsistent_fieldnames_none(self): """ Test that get_inconsistent_fieldnames returns an empty data and no checks fail @@ -19,8 +19,8 @@ class ChecksTestCase(TestCase): self.assertFalse(extra_keys) @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', - {'Set1': list(settings.CONFIG.keys())[:-1]}, + "constance.settings.CONFIG_FIELDSETS", + {"Set1": list(settings.CONFIG.keys())[:-1]}, ) def test_get_inconsistent_fieldnames_for_missing_keys(self): """ @@ -33,8 +33,8 @@ class ChecksTestCase(TestCase): self.assertEqual(1, len(check_fieldsets())) @mock.patch( - 'constance.settings.CONFIG_FIELDSETS', - {'Set1': [*settings.CONFIG.keys(), 'FORGOTTEN_KEY']}, + "constance.settings.CONFIG_FIELDSETS", + {"Set1": [*settings.CONFIG.keys(), "FORGOTTEN_KEY"]}, ) def test_get_inconsistent_fieldnames_for_extra_keys(self): """ @@ -46,7 +46,7 @@ class ChecksTestCase(TestCase): self.assertTrue(extra_keys) self.assertEqual(1, len(check_fieldsets())) - @mock.patch('constance.settings.CONFIG_FIELDSETS', {}) + @mock.patch("constance.settings.CONFIG_FIELDSETS", {}) def test_check_fieldsets(self): """check_fieldsets should not output warning if CONFIG_FIELDSETS is not defined.""" del settings.CONFIG_FIELDSETS diff --git a/tests/test_cli.py b/tests/test_cli.py index 68d8daf..d9083b1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -20,10 +20,10 @@ class CliTestCase(TransactionTestCase): def test_help(self): with contextlib.suppress(SystemExit): - call_command('constance', '--help') + call_command("constance", "--help") def test_list(self): - call_command('constance', 'list', stdout=self.out) + call_command("constance", "list", stdout=self.out) self.assertEqual( set(self.out.getvalue().splitlines()), @@ -51,16 +51,16 @@ class CliTestCase(TransactionTestCase): ) def test_get(self): - call_command('constance', *('get EMAIL_VALUE'.split()), stdout=self.out) + call_command("constance", *("get EMAIL_VALUE".split()), stdout=self.out) - self.assertEqual(self.out.getvalue().strip(), 'test@example.com') + self.assertEqual(self.out.getvalue().strip(), "test@example.com") def test_set(self): - call_command('constance', *('set EMAIL_VALUE blah@example.com'.split()), stdout=self.out) + call_command("constance", *("set EMAIL_VALUE blah@example.com".split()), stdout=self.out) - self.assertEqual(config.EMAIL_VALUE, 'blah@example.com') + self.assertEqual(config.EMAIL_VALUE, "blah@example.com") - call_command('constance', *('set', 'DATETIME_VALUE', '2011-09-24', '12:30:25'), stdout=self.out) + call_command("constance", *("set", "DATETIME_VALUE", "2011-09-24", "12:30:25"), stdout=self.out) expected = datetime(2011, 9, 24, 12, 30, 25) if settings.USE_TZ: @@ -70,50 +70,50 @@ class CliTestCase(TransactionTestCase): def test_get_invalid_name(self): self.assertRaisesMessage( CommandError, - 'NOT_A_REAL_CONFIG is not defined in settings.CONSTANCE_CONFIG', + "NOT_A_REAL_CONFIG is not defined in settings.CONSTANCE_CONFIG", call_command, - 'constance', - 'get', - 'NOT_A_REAL_CONFIG', + "constance", + "get", + "NOT_A_REAL_CONFIG", ) def test_set_invalid_name(self): self.assertRaisesMessage( CommandError, - 'NOT_A_REAL_CONFIG is not defined in settings.CONSTANCE_CONFIG', + "NOT_A_REAL_CONFIG is not defined in settings.CONSTANCE_CONFIG", call_command, - 'constance', - 'set', - 'NOT_A_REAL_CONFIG', - 'foo', + "constance", + "set", + "NOT_A_REAL_CONFIG", + "foo", ) def test_set_invalid_value(self): self.assertRaisesMessage( CommandError, - 'Enter a valid email address.', + "Enter a valid email address.", call_command, - 'constance', - 'set', - 'EMAIL_VALUE', - 'not a valid email', + "constance", + "set", + "EMAIL_VALUE", + "not a valid email", ) def test_set_invalid_multi_value(self): self.assertRaisesMessage( CommandError, - 'Enter a list of values.', + "Enter a list of values.", call_command, - 'constance', - 'set', - 'DATETIME_VALUE', - '2011-09-24 12:30:25', + "constance", + "set", + "DATETIME_VALUE", + "2011-09-24 12:30:25", ) def test_delete_stale_records(self): initial_count = Constance.objects.count() - Constance.objects.create(key='STALE_KEY', value=None) - call_command('constance', 'remove_stale_keys', stdout=self.out) + Constance.objects.create(key="STALE_KEY", value=None) + call_command("constance", "remove_stale_keys", stdout=self.out) self.assertEqual(Constance.objects.count(), initial_count, msg=self.out) diff --git a/tests/test_codecs.py b/tests/test_codecs.py index cf5f67b..48c306c 100644 --- a/tests/test_codecs.py +++ b/tests/test_codecs.py @@ -16,16 +16,16 @@ class TestJSONSerialization(TestCase): self.datetime = datetime(2023, 10, 5, 15, 30, 0) self.date = date(2023, 10, 5) self.time = time(15, 30, 0) - self.decimal = Decimal('10.5') - self.uuid = uuid.UUID('12345678123456781234567812345678') - self.string = 'test' + self.decimal = Decimal("10.5") + self.uuid = uuid.UUID("12345678123456781234567812345678") + self.string = "test" self.integer = 42 self.float = 3.14 self.boolean = True self.none = None self.timedelta = timedelta(days=1, hours=2, minutes=3) self.list = [1, 2, self.date] - self.dict = {'key': self.date, 'key2': 1} + self.dict = {"key": self.date, "key2": 1} def test_serializes_and_deserializes_default_types(self): self.assertEqual(dumps(self.datetime), '{"__type__": "datetime", "__value__": "2023-10-05T15:30:00"}') @@ -65,18 +65,18 @@ class TestJSONSerialization(TestCase): self.assertEqual(t, loads(dumps(t))) def test_invalid_deserialization(self): - with self.assertRaisesRegex(ValueError, 'Expecting value'): - loads('THIS_IS_NOT_RIGHT') - with self.assertRaisesRegex(ValueError, 'Invalid object'): + with self.assertRaisesRegex(ValueError, "Expecting value"): + loads("THIS_IS_NOT_RIGHT") + with self.assertRaisesRegex(ValueError, "Invalid object"): loads('{"__type__": "THIS_IS_NOT_RIGHT", "__value__": "test", "THIS_IS_NOT_RIGHT": "THIS_IS_NOT_RIGHT"}') - with self.assertRaisesRegex(ValueError, 'Unsupported type'): + with self.assertRaisesRegex(ValueError, "Unsupported type"): loads('{"__type__": "THIS_IS_NOT_RIGHT", "__value__": "test"}') def test_handles_unknown_type(self): class UnknownType: pass - with self.assertRaisesRegex(TypeError, 'Object of type UnknownType is not JSON serializable'): + with self.assertRaisesRegex(TypeError, "Object of type UnknownType is not JSON serializable"): dumps(UnknownType()) def test_custom_type_serialization(self): @@ -84,25 +84,25 @@ class TestJSONSerialization(TestCase): def __init__(self, value): self.value = value - register_type(CustomType, 'custom', lambda o: o.value, lambda o: CustomType(o)) - custom_data = CustomType('test') + register_type(CustomType, "custom", lambda o: o.value, lambda o: CustomType(o)) + custom_data = CustomType("test") json_data = dumps(custom_data) self.assertEqual(json_data, '{"__type__": "custom", "__value__": "test"}') deserialized_data = loads(json_data) self.assertTrue(isinstance(deserialized_data, CustomType)) - self.assertEqual(deserialized_data.value, 'test') + self.assertEqual(deserialized_data.value, "test") def test_register_known_type(self): - with self.assertRaisesRegex(ValueError, 'Discriminator must be specified'): - register_type(int, '', lambda o: o.value, lambda o: int(o)) - with self.assertRaisesRegex(ValueError, 'Type with discriminator default is already registered'): - register_type(int, 'default', lambda o: o.value, lambda o: int(o)) - register_type(int, 'new_custom_type', lambda o: o.value, lambda o: int(o)) - with self.assertRaisesRegex(ValueError, 'Type with discriminator new_custom_type is already registered'): - register_type(int, 'new_custom_type', lambda o: o.value, lambda o: int(o)) + with self.assertRaisesRegex(ValueError, "Discriminator must be specified"): + register_type(int, "", lambda o: o.value, lambda o: int(o)) + with self.assertRaisesRegex(ValueError, "Type with discriminator default is already registered"): + register_type(int, "default", lambda o: o.value, lambda o: int(o)) + register_type(int, "new_custom_type", lambda o: o.value, lambda o: int(o)) + with self.assertRaisesRegex(ValueError, "Type with discriminator new_custom_type is already registered"): + register_type(int, "new_custom_type", lambda o: o.value, lambda o: int(o)) def test_nested_collections(self): - data = {'key': [[[[{'key': self.date}]]]]} + data = {"key": [[[[{"key": self.date}]]]]} self.assertEqual( dumps(data), ( diff --git a/tests/test_form.py b/tests/test_form.py index 105d2ef..74ea9ee 100644 --- a/tests/test_form.py +++ b/tests/test_form.py @@ -8,16 +8,16 @@ class TestForm(TestCase): def test_form_field_types(self): f = ConstanceForm({}) - self.assertIsInstance(f.fields['INT_VALUE'], fields.IntegerField) - self.assertIsInstance(f.fields['BOOL_VALUE'], fields.BooleanField) - self.assertIsInstance(f.fields['STRING_VALUE'], fields.CharField) - self.assertIsInstance(f.fields['DECIMAL_VALUE'], fields.DecimalField) - self.assertIsInstance(f.fields['DATETIME_VALUE'], fields.SplitDateTimeField) - self.assertIsInstance(f.fields['TIMEDELTA_VALUE'], fields.DurationField) - self.assertIsInstance(f.fields['FLOAT_VALUE'], fields.FloatField) - self.assertIsInstance(f.fields['DATE_VALUE'], fields.DateField) - self.assertIsInstance(f.fields['TIME_VALUE'], fields.TimeField) + self.assertIsInstance(f.fields["INT_VALUE"], fields.IntegerField) + self.assertIsInstance(f.fields["BOOL_VALUE"], fields.BooleanField) + self.assertIsInstance(f.fields["STRING_VALUE"], fields.CharField) + self.assertIsInstance(f.fields["DECIMAL_VALUE"], fields.DecimalField) + self.assertIsInstance(f.fields["DATETIME_VALUE"], fields.SplitDateTimeField) + self.assertIsInstance(f.fields["TIMEDELTA_VALUE"], fields.DurationField) + self.assertIsInstance(f.fields["FLOAT_VALUE"], fields.FloatField) + self.assertIsInstance(f.fields["DATE_VALUE"], fields.DateField) + self.assertIsInstance(f.fields["TIME_VALUE"], fields.TimeField) # from CONSTANCE_ADDITIONAL_FIELDS - self.assertIsInstance(f.fields['CHOICE_VALUE'], fields.ChoiceField) - self.assertIsInstance(f.fields['EMAIL_VALUE'], fields.EmailField) + self.assertIsInstance(f.fields["CHOICE_VALUE"], fields.ChoiceField) + self.assertIsInstance(f.fields["EMAIL_VALUE"], fields.EmailField) diff --git a/tests/test_pytest_overrides.py b/tests/test_pytest_overrides.py index c6b7a80..b218533 100644 --- a/tests/test_pytest_overrides.py +++ b/tests/test_pytest_overrides.py @@ -42,10 +42,10 @@ try: """Assert that the class decorator changes config.BOOL_VALUE.""" assert not config.BOOL_VALUE - @pytest.mark.override_config(BOOL_VALUE='True') + @pytest.mark.override_config(BOOL_VALUE="True") def test_override_config_on_overridden_value(self): """Ensure that method mark decorator changes already overridden value for class.""" - assert config.BOOL_VALUE == 'True' + assert config.BOOL_VALUE == "True" def test_fixture_override_config(override_config): """ @@ -66,7 +66,7 @@ except ImportError: class PytestTests(unittest.TestCase): def setUp(self): - self.skipTest('Skip all pytest tests when using unittest') + self.skipTest("Skip all pytest tests when using unittest") def test_do_not_skip_silently(self): """If no at least one test present, unittest silently skips module.""" diff --git a/tests/test_utils.py b/tests/test_utils.py index e403c9b..531426c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -11,32 +11,32 @@ from constance.utils import get_values_for_keys class UtilsTestCase(TestCase): def test_set_value_validation(self): - self.assertRaisesMessage(ValidationError, 'Enter a whole number.', _set_constance_value, 'INT_VALUE', 'foo') + self.assertRaisesMessage(ValidationError, "Enter a whole number.", _set_constance_value, "INT_VALUE", "foo") self.assertRaisesMessage( ValidationError, - 'Enter a valid email address.', + "Enter a valid email address.", _set_constance_value, - 'EMAIL_VALUE', - 'not a valid email', + "EMAIL_VALUE", + "not a valid email", ) self.assertRaisesMessage( ValidationError, - 'Enter a valid date.', + "Enter a valid date.", _set_constance_value, - 'DATETIME_VALUE', + "DATETIME_VALUE", ( - '2000-00-00', - '99:99:99', + "2000-00-00", + "99:99:99", ), ) self.assertRaisesMessage( ValidationError, - 'Enter a valid time.', + "Enter a valid time.", _set_constance_value, - 'DATETIME_VALUE', + "DATETIME_VALUE", ( - '2016-01-01', - '99:99:99', + "2016-01-01", + "99:99:99", ), ) @@ -44,37 +44,37 @@ class UtilsTestCase(TestCase): self.assertEqual( get_values(), { - 'FLOAT_VALUE': 3.1415926536, - 'BOOL_VALUE': True, - 'EMAIL_VALUE': 'test@example.com', - 'INT_VALUE': 1, - 'CHOICE_VALUE': 'yes', - 'TIME_VALUE': datetime.time(23, 59, 59), - 'DATE_VALUE': datetime.date(2010, 12, 24), - 'TIMEDELTA_VALUE': datetime.timedelta(days=1, hours=2, minutes=3), - 'LINEBREAK_VALUE': 'Spam spam', - 'DECIMAL_VALUE': Decimal('0.1'), - 'STRING_VALUE': 'Hello world', - 'DATETIME_VALUE': datetime.datetime(2010, 8, 23, 11, 29, 24), - 'LIST_VALUE': [1, '1', datetime.date(2019, 1, 1)], - 'JSON_VALUE': { - 'key': 'value', - 'key2': 2, - 'key3': [1, 2, 3], - 'key4': {'key': 'value'}, - 'key5': datetime.date(2019, 1, 1), - 'key6': None, + "FLOAT_VALUE": 3.1415926536, + "BOOL_VALUE": True, + "EMAIL_VALUE": "test@example.com", + "INT_VALUE": 1, + "CHOICE_VALUE": "yes", + "TIME_VALUE": datetime.time(23, 59, 59), + "DATE_VALUE": datetime.date(2010, 12, 24), + "TIMEDELTA_VALUE": datetime.timedelta(days=1, hours=2, minutes=3), + "LINEBREAK_VALUE": "Spam spam", + "DECIMAL_VALUE": Decimal("0.1"), + "STRING_VALUE": "Hello world", + "DATETIME_VALUE": datetime.datetime(2010, 8, 23, 11, 29, 24), + "LIST_VALUE": [1, "1", datetime.date(2019, 1, 1)], + "JSON_VALUE": { + "key": "value", + "key2": 2, + "key3": [1, 2, 3], + "key4": {"key": "value"}, + "key5": datetime.date(2019, 1, 1), + "key6": None, }, }, ) def test_get_values_for_keys(self): self.assertEqual( - get_values_for_keys(['BOOL_VALUE', 'CHOICE_VALUE', 'LINEBREAK_VALUE']), + get_values_for_keys(["BOOL_VALUE", "CHOICE_VALUE", "LINEBREAK_VALUE"]), { - 'BOOL_VALUE': True, - 'CHOICE_VALUE': 'yes', - 'LINEBREAK_VALUE': 'Spam spam', + "BOOL_VALUE": True, + "CHOICE_VALUE": "yes", + "LINEBREAK_VALUE": "Spam spam", }, ) @@ -87,9 +87,9 @@ class UtilsTestCase(TestCase): AttributeError, '"OLD_VALUE, BOLD_VALUE" keys not found in configuration.', get_values_for_keys, - ['BOOL_VALUE', 'OLD_VALUE', 'BOLD_VALUE'], + ["BOOL_VALUE", "OLD_VALUE", "BOLD_VALUE"], ) def test_get_values_for_keys_invalid_input_type(self): with self.assertRaises(TypeError): - get_values_for_keys('key1') + get_values_for_keys("key1") diff --git a/tests/urls.py b/tests/urls.py index dfc7362..083932c 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -2,5 +2,5 @@ from django.contrib import admin from django.urls import path urlpatterns = [ - path('admin/', admin.site.urls), + path("admin/", admin.site.urls), ]