diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py index 4296a703aa..76345e92f5 100644 --- a/django/contrib/auth/admin.py +++ b/django/contrib/auth/admin.py @@ -83,7 +83,11 @@ class UserAdmin(admin.ModelAdmin): def get_urls(self): return [ - url(r'^(.+)/password/$', self.admin_site.admin_view(self.user_change_password), name='auth_user_password_change'), + url( + r'^(.+)/password/$', + self.admin_site.admin_view(self.user_change_password), + name='auth_user_password_change', + ), ] + super(UserAdmin, self).get_urls() def lookup_allowed(self, lookup, value): diff --git a/django/contrib/auth/migrations/0001_initial.py b/django/contrib/auth/migrations/0001_initial.py index fcc9d05318..7df5603879 100644 --- a/django/contrib/auth/migrations/0001_initial.py +++ b/django/contrib/auth/migrations/0001_initial.py @@ -58,16 +58,42 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('password', models.CharField(max_length=128, verbose_name='password')), ('last_login', models.DateTimeField(default=timezone.now, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, max_length=30, verbose_name='username', validators=[validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username.', 'invalid')])), + ('is_superuser', models.BooleanField( + default=False, + help_text='Designates that this user has all permissions without explicitly assigning them.', + verbose_name='superuser status' + )), + ('username', models.CharField( + help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, + max_length=30, verbose_name='username', + validators=[validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username.', 'invalid')] + )), ('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)), ('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)), ('email', models.EmailField(max_length=75, verbose_name='email address', blank=True)), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('is_staff', models.BooleanField( + default=False, help_text='Designates whether the user can log into this admin site.', + verbose_name='staff status' + )), + ('is_active', models.BooleanField( + default=True, verbose_name='active', help_text=( + 'Designates whether this user should be treated as active. Unselect this instead of deleting ' + 'accounts.' + ) + )), ('date_joined', models.DateTimeField(default=timezone.now, verbose_name='date joined')), - ('groups', models.ManyToManyField(to='auth.Group', verbose_name='groups', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user')), - ('user_permissions', models.ManyToManyField(to='auth.Permission', verbose_name='user permissions', blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user')), + ('groups', models.ManyToManyField( + to='auth.Group', verbose_name='groups', blank=True, related_name='user_set', + related_query_name='user', help_text=( + 'The groups this user belongs to. A user will get all permissions granted to each of their ' + 'groups.' + ) + )), + ('user_permissions', models.ManyToManyField( + to='auth.Permission', verbose_name='user permissions', blank=True, + help_text='Specific permissions for this user.', related_name='user_set', + related_query_name='user') + ), ], options={ 'swappable': 'AUTH_USER_MODEL', diff --git a/django/contrib/auth/migrations/0004_alter_user_username_opts.py b/django/contrib/auth/migrations/0004_alter_user_username_opts.py index 0f7bfdf3a7..151cda7b74 100644 --- a/django/contrib/auth/migrations/0004_alter_user_username_opts.py +++ b/django/contrib/auth/migrations/0004_alter_user_username_opts.py @@ -16,6 +16,15 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='user', name='username', - field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=30, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, verbose_name='username'), + field=models.CharField( + error_messages={'unique': 'A user with that username already exists.'}, max_length=30, + validators=[django.core.validators.RegexValidator( + '^[\\w.@+-]+$', + 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', + 'invalid' + )], + help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', + unique=True, verbose_name='username' + ), ), ] diff --git a/django/contrib/flatpages/migrations/0001_initial.py b/django/contrib/flatpages/migrations/0001_initial.py index 3281e54bf6..13e417b41b 100644 --- a/django/contrib/flatpages/migrations/0001_initial.py +++ b/django/contrib/flatpages/migrations/0001_initial.py @@ -19,8 +19,16 @@ class Migration(migrations.Migration): ('title', models.CharField(max_length=200, verbose_name='title')), ('content', models.TextField(verbose_name='content', blank=True)), ('enable_comments', models.BooleanField(default=False, verbose_name='enable comments')), - ('template_name', models.CharField(help_text="Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'.", max_length=70, verbose_name='template name', blank=True)), - ('registration_required', models.BooleanField(default=False, help_text='If this is checked, only logged-in users will be able to view the page.', verbose_name='registration required')), + ('template_name', models.CharField( + help_text=( + "Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use " + "'flatpages/default.html'." + ), max_length=70, verbose_name='template name', blank=True + )), + ('registration_required', models.BooleanField( + default=False, help_text='If this is checked, only logged-in users will be able to view the page.', + verbose_name='registration required' + )), ('sites', models.ManyToManyField(to='sites.Site', verbose_name='sites')), ], options={ diff --git a/django/contrib/redirects/migrations/0001_initial.py b/django/contrib/redirects/migrations/0001_initial.py index cfd5dcf5a3..905ec266aa 100644 --- a/django/contrib/redirects/migrations/0001_initial.py +++ b/django/contrib/redirects/migrations/0001_initial.py @@ -21,8 +21,15 @@ class Migration(migrations.Migration): on_delete=models.CASCADE, verbose_name='site', )), - ('old_path', models.CharField(help_text="This should be an absolute path, excluding the domain name. Example: '/events/search/'.", max_length=200, verbose_name='redirect from', db_index=True)), - ('new_path', models.CharField(help_text="This can be either an absolute path (as above) or a full URL starting with 'http://'.", max_length=200, verbose_name='redirect to', blank=True)), + ('old_path', models.CharField( + help_text=( + "This should be an absolute path, excluding the domain name. Example: '/events/search/'." + ), max_length=200, verbose_name='redirect from', db_index=True + )), + ('new_path', models.CharField( + help_text="This can be either an absolute path (as above) or a full URL starting with 'http://'.", + max_length=200, verbose_name='redirect to', blank=True + )), ], options={ 'ordering': ('old_path',), diff --git a/django/contrib/sessions/migrations/0001_initial.py b/django/contrib/sessions/migrations/0001_initial.py index 0a4acc9382..e9fd627b79 100644 --- a/django/contrib/sessions/migrations/0001_initial.py +++ b/django/contrib/sessions/migrations/0001_initial.py @@ -14,7 +14,9 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Session', fields=[ - ('session_key', models.CharField(max_length=40, serialize=False, verbose_name='session key', primary_key=True)), + ('session_key', models.CharField( + max_length=40, serialize=False, verbose_name='session key', primary_key=True + )), ('session_data', models.TextField(verbose_name='session data')), ('expire_date', models.DateTimeField(verbose_name='expire date', db_index=True)), ], diff --git a/django/contrib/sites/migrations/0001_initial.py b/django/contrib/sites/migrations/0001_initial.py index 84ad0cd408..b1803682ae 100644 --- a/django/contrib/sites/migrations/0001_initial.py +++ b/django/contrib/sites/migrations/0001_initial.py @@ -15,7 +15,9 @@ class Migration(migrations.Migration): name='Site', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('domain', models.CharField(max_length=100, verbose_name='domain name', validators=[_simple_domain_name_validator])), + ('domain', models.CharField( + max_length=100, verbose_name='domain name', validators=[_simple_domain_name_validator] + )), ('name', models.CharField(max_length=50, verbose_name='display name')), ], options={ diff --git a/django/contrib/sites/migrations/0002_alter_domain_unique.py b/django/contrib/sites/migrations/0002_alter_domain_unique.py index e7f414fb5c..468718cde3 100644 --- a/django/contrib/sites/migrations/0002_alter_domain_unique.py +++ b/django/contrib/sites/migrations/0002_alter_domain_unique.py @@ -15,6 +15,9 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='site', name='domain', - field=models.CharField(max_length=100, unique=True, validators=[django.contrib.sites.models._simple_domain_name_validator], verbose_name='domain name'), + field=models.CharField( + max_length=100, unique=True, validators=[django.contrib.sites.models._simple_domain_name_validator], + verbose_name='domain name' + ), ), ] diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py index 3e0a9e5df3..9b9e350f4b 100644 --- a/django/core/management/commands/inspectdb.py +++ b/django/core/management/commands/inspectdb.py @@ -92,7 +92,10 @@ class Command(BaseCommand): extra_params['unique'] = True if is_relation: - rel_to = "self" if relations[column_name][1] == table_name else table2model(relations[column_name][1]) + rel_to = ( + "self" if relations[column_name][1] == table_name + else table2model(relations[column_name][1]) + ) if rel_to in known_models: field_type = 'ForeignKey(%s' % rel_to else: diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index ff506d50cb..b64169bb62 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -124,14 +124,15 @@ def Deserializer(object_list, **options): # Handle M2M relations if field.remote_field and isinstance(field.remote_field, models.ManyToManyRel): - if hasattr(field.remote_field.model._default_manager, 'get_by_natural_key'): + model = field.remote_field.model + if hasattr(model._default_manager, 'get_by_natural_key'): def m2m_convert(value): if hasattr(value, '__iter__') and not isinstance(value, six.text_type): - return field.remote_field.model._default_manager.db_manager(db).get_by_natural_key(*value).pk + return model._default_manager.db_manager(db).get_by_natural_key(*value).pk else: - return force_text(field.remote_field.model._meta.pk.to_python(value), strings_only=True) + return force_text(model._meta.pk.to_python(value), strings_only=True) else: - m2m_convert = lambda v: force_text(field.remote_field.model._meta.pk.to_python(v), strings_only=True) + m2m_convert = lambda v: force_text(model._meta.pk.to_python(v), strings_only=True) try: m2m_data[field.name] = [] @@ -142,21 +143,24 @@ def Deserializer(object_list, **options): # Handle FK fields elif field.remote_field and isinstance(field.remote_field, models.ManyToOneRel): + model = field.remote_field.model if field_value is not None: try: - if hasattr(field.remote_field.model._default_manager, 'get_by_natural_key'): + default_manager = model._default_manager + field_name = field.remote_field.field_name + if hasattr(default_manager, 'get_by_natural_key'): if hasattr(field_value, '__iter__') and not isinstance(field_value, six.text_type): - obj = field.remote_field.model._default_manager.db_manager(db).get_by_natural_key(*field_value) + obj = default_manager.db_manager(db).get_by_natural_key(*field_value) value = getattr(obj, field.remote_field.field_name) # If this is a natural foreign key to an object that # has a FK/O2O as the foreign key, use the FK value - if field.remote_field.model._meta.pk.remote_field: + if model._meta.pk.remote_field: value = value.pk else: - value = field.remote_field.model._meta.get_field(field.remote_field.field_name).to_python(field_value) + value = model._meta.get_field(field_name).to_python(field_value) data[field.attname] = value else: - data[field.attname] = field.remote_field.model._meta.get_field(field.remote_field.field_name).to_python(field_value) + data[field.attname] = model._meta.get_field(field_name).to_python(field_value) except Exception as e: raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value) else: diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index 9bddda46da..44d745d55d 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -236,12 +236,13 @@ class Deserializer(base.Deserializer): if node.getElementsByTagName('None'): return None else: - if hasattr(field.remote_field.model._default_manager, 'get_by_natural_key'): + model = field.remote_field.model + if hasattr(model._default_manager, 'get_by_natural_key'): keys = node.getElementsByTagName('natural') if keys: # If there are 'natural' subelements, it must be a natural key field_value = [getInnerText(k).strip() for k in keys] - obj = field.remote_field.model._default_manager.db_manager(self.db).get_by_natural_key(*field_value) + obj = model._default_manager.db_manager(self.db).get_by_natural_key(*field_value) obj_pk = getattr(obj, field.remote_field.field_name) # If this is a natural foreign key to an object that # has a FK/O2O as the foreign key, use the FK value @@ -250,29 +251,31 @@ class Deserializer(base.Deserializer): else: # Otherwise, treat like a normal PK field_value = getInnerText(node).strip() - obj_pk = field.remote_field.model._meta.get_field(field.remote_field.field_name).to_python(field_value) + obj_pk = model._meta.get_field(field.remote_field.field_name).to_python(field_value) return obj_pk else: field_value = getInnerText(node).strip() - return field.remote_field.model._meta.get_field(field.remote_field.field_name).to_python(field_value) + return model._meta.get_field(field.remote_field.field_name).to_python(field_value) def _handle_m2m_field_node(self, node, field): """ Handle a node for a ManyToManyField. """ - if hasattr(field.remote_field.model._default_manager, 'get_by_natural_key'): + model = field.remote_field.model + default_manager = model._default_manager + if hasattr(default_manager, 'get_by_natural_key'): def m2m_convert(n): keys = n.getElementsByTagName('natural') if keys: # If there are 'natural' subelements, it must be a natural key field_value = [getInnerText(k).strip() for k in keys] - obj_pk = field.remote_field.model._default_manager.db_manager(self.db).get_by_natural_key(*field_value).pk + obj_pk = default_manager.db_manager(self.db).get_by_natural_key(*field_value).pk else: # Otherwise, treat like a normal PK value. - obj_pk = field.remote_field.model._meta.pk.to_python(n.getAttribute('pk')) + obj_pk = model._meta.pk.to_python(n.getAttribute('pk')) return obj_pk else: - m2m_convert = lambda n: field.remote_field.model._meta.pk.to_python(n.getAttribute('pk')) + m2m_convert = lambda n: model._meta.pk.to_python(n.getAttribute('pk')) return [m2m_convert(c) for c in node.getElementsByTagName("object")] def _get_model_from_node(self, node, attr): diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py index b2181818ea..513bb543d1 100644 --- a/django/db/migrations/autodetector.py +++ b/django/db/migrations/autodetector.py @@ -468,7 +468,11 @@ class MigrationAutodetector(object): ) ) self.renamed_models[app_label, model_name] = rem_model_name - self.renamed_models_rel['%s.%s' % (rem_model_state.app_label, rem_model_state.name)] = '%s.%s' % (model_state.app_label, model_state.name) + renamed_models_rel_key = '%s.%s' % (rem_model_state.app_label, rem_model_state.name) + self.renamed_models_rel[renamed_models_rel_key] = '%s.%s' % ( + model_state.app_label, + model_state.name, + ) self.old_model_keys.remove((rem_app_label, rem_model_name)) self.old_model_keys.append((app_label, model_name)) break @@ -505,7 +509,8 @@ class MigrationAutodetector(object): related_fields[field.name] = field # through will be none on M2Ms on swapped-out models; # we can treat lack of through as auto_created=True, though. - if getattr(field.remote_field, "through", None) and not field.remote_field.through._meta.auto_created: + if (getattr(field.remote_field, "through", None) + and not field.remote_field.through._meta.auto_created): related_fields[field.name] = field for field in model_opts.local_many_to_many: if field.remote_field.model: @@ -681,7 +686,8 @@ class MigrationAutodetector(object): related_fields[field.name] = field # through will be none on M2Ms on swapped-out models; # we can treat lack of through as auto_created=True, though. - if getattr(field.remote_field, "through", None) and not field.remote_field.through._meta.auto_created: + if (getattr(field.remote_field, "through", None) + and not field.remote_field.through._meta.auto_created): related_fields[field.name] = field for field in model._meta.local_many_to_many: if field.remote_field.model: diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py index 93aa8e61f7..fac33c3ce7 100644 --- a/django/db/migrations/loader.py +++ b/django/db/migrations/loader.py @@ -119,7 +119,10 @@ class MigrationLoader(object): if hasattr(migration_module.Migration, "forwards"): south_style_migrations = True break - self.disk_migrations[app_config.label, migration_name] = migration_module.Migration(migration_name, app_config.label) + self.disk_migrations[app_config.label, migration_name] = migration_module.Migration( + migration_name, + app_config.label, + ) if south_style_migrations: self.unmigrated_apps.add(app_config.label) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 609d262127..2e2ec38335 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -346,7 +346,10 @@ class RelatedField(Field): return None def set_attributes_from_rel(self): - self.name = self.name or (self.remote_field.model._meta.model_name + '_' + self.remote_field.model._meta.pk.name) + self.name = ( + self.name or + (self.remote_field.model._meta.model_name + '_' + self.remote_field.model._meta.pk.name) + ) if self.verbose_name is None: self.verbose_name = self.remote_field.model._meta.verbose_name self.remote_field.set_field_name() @@ -830,7 +833,9 @@ def create_foreign_related_manager(superclass, rel): if self.field.get_local_related_value(obj) == val: old_ids.add(obj.pk) else: - raise self.field.remote_field.model.DoesNotExist("%r is not related to %r." % (obj, self.instance)) + raise self.field.remote_field.model.DoesNotExist( + "%r is not related to %r." % (obj, self.instance) + ) self._clear(self.filter(pk__in=old_ids), bulk) remove.alters_data = True @@ -955,7 +960,8 @@ def create_many_related_manager(superclass, rel, reverse): self.core_filters = {} for lh_field, rh_field in self.source_field.related_fields: - self.core_filters['%s__%s' % (self.query_field_name, rh_field.name)] = getattr(instance, rh_field.attname) + core_filter_key = '%s__%s' % (self.query_field_name, rh_field.name) + self.core_filters[core_filter_key] = getattr(instance, rh_field.attname) self.related_val = self.source_field.get_foreign_related_value(instance) if None in self.related_val: @@ -1688,7 +1694,10 @@ class ForeignObject(RelatedField): if isinstance(self.remote_field.model, six.string_types): kwargs['to'] = self.remote_field.model else: - kwargs['to'] = "%s.%s" % (self.remote_field.model._meta.app_label, self.remote_field.model._meta.object_name) + kwargs['to'] = "%s.%s" % ( + self.remote_field.model._meta.app_label, + self.remote_field.model._meta.object_name, + ) # If swappable is True, then see if we're actually pointing to the target # of a swap. swappable_setting = self.swappable_setting @@ -1999,7 +2008,8 @@ class ForeignKey(ForeignObject): kwargs['db_constraint'] = self.db_constraint # Rel needs more work. to_meta = getattr(self.remote_field.model, "_meta", None) - if self.remote_field.field_name and (not to_meta or (to_meta.pk and self.remote_field.field_name != to_meta.pk.name)): + if self.remote_field.field_name and ( + not to_meta or (to_meta.pk and self.remote_field.field_name != to_meta.pk.name)): kwargs['to_field'] = self.remote_field.field_name return name, path, args, kwargs diff --git a/django/forms/models.py b/django/forms/models.py index 651749a356..0fba08855f 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -788,8 +788,12 @@ class BaseModelFormSet(BaseFormSet): # True, so check for that as well. def pk_is_not_editable(pk): - return ((not pk.editable) or (pk.auto_created or isinstance(pk, AutoField)) - or (pk.remote_field and pk.remote_field.parent_link and pk_is_not_editable(pk.remote_field.model._meta.pk))) + return ( + (not pk.editable) or (pk.auto_created or isinstance(pk, AutoField)) or ( + pk.remote_field and pk.remote_field.parent_link + and pk_is_not_editable(pk.remote_field.model._meta.pk) + ) + ) if pk_is_not_editable(pk) or pk.name not in form.fields: if form.is_bound: # If we're adding the related instance, ignore its primary key diff --git a/django/test/client.py b/django/test/client.py index 8d46ea629a..a1ee223fdb 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -655,7 +655,10 @@ class Client(RequestFactory): def _parse_json(self, response, **extra): if 'application/json' not in response.get('Content-Type'): - raise ValueError('Content-Type header is "{0}", not "application/json"'.format(response.get('Content-Type'))) + raise ValueError( + 'Content-Type header is "{0}", not "application/json"' + .format(response.get('Content-Type')) + ) return json.loads(response.content.decode(), **extra) def _handle_redirects(self, response, **extra): diff --git a/django/views/debug.py b/django/views/debug.py index 55357b3344..b6201ab54a 100644 --- a/django/views/debug.py +++ b/django/views/debug.py @@ -862,12 +862,12 @@ Installed Middleware: {% if postmortem %}Django tried loading these templates, in this order: {% for entry in postmortem %} Using engine {{ entry.backend.name }}: -{% if entry.tried %}{% for attempt in entry.tried %} * {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }}) +{% if entry.tried %}{% for attempt in entry.tried %}""" +""" * {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }}) {% endfor %}{% else %} This engine did not provide a list of tried templates. {% endif %}{% endfor %} {% else %}No templates were found because your 'TEMPLATES' setting is not configured. -{% endif %} -{% endif %}{% if template_info %} +{% endif %}{% endif %}{% if template_info %} Template error: In template {{ template_info.name }}, error at line {{ template_info.line }} {{ template_info.message }}""" @@ -1044,7 +1044,8 @@ Exception Value: {{ exception_value|force_escape }} """) -TECHNICAL_500_TEXT_TEMPLATE = ("""{% firstof exception_type 'Report' %}{% if request %} at {{ request.path_info }}{% endif %} +TECHNICAL_500_TEXT_TEMPLATE = ("""""" +"""{% firstof exception_type 'Report' %}{% if request %} at {{ request.path_info }}{% endif %} {% firstof exception_value 'No exception message supplied' %} {% if request %} Request Method: {{ request.META.REQUEST_METHOD }} @@ -1062,7 +1063,8 @@ Installed Middleware: {% if postmortem %}Django tried loading these templates, in this order: {% for entry in postmortem %} Using engine {{ entry.backend.name }}: -{% if entry.tried %}{% for attempt in entry.tried %} * {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }}) +{% if entry.tried %}{% for attempt in entry.tried %}""" +""" * {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }}) {% endfor %}{% else %} This engine did not provide a list of tried templates. {% endif %}{% endfor %} {% else %}No templates were found because your 'TEMPLATES' setting is not configured. diff --git a/docs/conf.py b/docs/conf.py index a8006e2f94..10caf0ce8a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -272,9 +272,13 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - ('ref/django-admin', 'django-admin', 'Utility script for the Django Web framework', ['Django Software Foundation'], 1), -] +man_pages = [( + 'ref/django-admin', + 'django-admin', + 'Utility script for the Django Web framework', + ['Django Software Foundation'], + 1 +), ] # -- Options for Texinfo output ------------------------------------------------ diff --git a/setup.cfg b/setup.cfg index 64b31f97d5..a0b89d02e5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,7 +4,7 @@ install-script = scripts/rpm-install.sh [flake8] exclude = build,.git,./django/utils/lru_cache.py,./django/utils/six.py,./django/conf/app_template/*,./django/dispatch/weakref_backports.py,./tests/.env,./xmlrunner,tests/view_tests/tests/py3_test_debug.py -ignore = E123,E128,E402,E501,W503,E731,W601 +ignore = E123,E128,E402,W503,E731,W601 max-line-length = 119 [isort] diff --git a/tests/admin_changelist/tests.py b/tests/admin_changelist/tests.py index 5e773bcb9a..005aad6a3b 100644 --- a/tests/admin_changelist/tests.py +++ b/tests/admin_changelist/tests.py @@ -227,12 +227,23 @@ class ChangeListTests(TestCase): context = Context({'cl': cl}) table_output = template.render(context) # make sure that hidden fields are in the correct place - hiddenfields_div = '
' % new_child.id + hiddenfields_div = ( + '
' + '' + '
' + ) % new_child.id self.assertInHTML(hiddenfields_div, table_output, msg_prefix='Failed to find hidden fields') # make sure that list editable fields are rendered in divs correctly - editable_name_field = '' - self.assertInHTML('%s' % editable_name_field, table_output, msg_prefix='Failed to find "name" list_editable field') + editable_name_field = ( + '' + ) + self.assertInHTML( + '%s' % editable_name_field, + table_output, + msg_prefix='Failed to find "name" list_editable field', + ) def test_result_list_editable(self): """ diff --git a/tests/admin_checks/tests.py b/tests/admin_checks/tests.py index 4544ddd382..280af17e1f 100644 --- a/tests/admin_checks/tests.py +++ b/tests/admin_checks/tests.py @@ -340,7 +340,10 @@ class SystemChecksTestCase(SimpleTestCase): self.assertEqual(errors, expected) def test_generic_inline_model_admin_non_gfk_ct_field(self): - "A GenericInlineModelAdmin raises problems if the ct_field points to a field that isn't part of a GenericForeignKey" + """ + A GenericInlineModelAdmin raises problems if the ct_field points to a + field that isn't part of a GenericForeignKey. + """ class InfluenceInline(GenericStackedInline): model = Influence ct_field = 'name' @@ -351,7 +354,8 @@ class SystemChecksTestCase(SimpleTestCase): errors = SongAdmin(Song, AdminSite()).check() expected = [ checks.Error( - "'admin_checks.Influence' has no GenericForeignKey using content type field 'name' and object ID field 'object_id'.", + "'admin_checks.Influence' has no GenericForeignKey using " + "content type field 'name' and object ID field 'object_id'.", hint=None, obj=InfluenceInline, id='admin.E304', @@ -360,7 +364,10 @@ class SystemChecksTestCase(SimpleTestCase): self.assertEqual(errors, expected) def test_generic_inline_model_admin_non_gfk_fk_field(self): - "A GenericInlineModelAdmin raises problems if the ct_fk_field points to a field that isn't part of a GenericForeignKey" + """ + A GenericInlineModelAdmin raises problems if the ct_fk_field points to + a field that isn't part of a GenericForeignKey. + """ class InfluenceInline(GenericStackedInline): model = Influence ct_fk_field = 'name' @@ -371,7 +378,8 @@ class SystemChecksTestCase(SimpleTestCase): errors = SongAdmin(Song, AdminSite()).check() expected = [ checks.Error( - "'admin_checks.Influence' has no GenericForeignKey using content type field 'content_type' and object ID field 'name'.", + "'admin_checks.Influence' has no GenericForeignKey using " + "content type field 'content_type' and object ID field 'name'.", hint=None, obj=InfluenceInline, id='admin.E304', @@ -389,8 +397,8 @@ class SystemChecksTestCase(SimpleTestCase): errors = RawIdNonexistingAdmin(Album, AdminSite()).check() expected = [ checks.Error( - ("The value of 'raw_id_fields[0]' refers to 'nonexisting', which is " - "not an attribute of 'admin_checks.Album'."), + "The value of 'raw_id_fields[0]' refers to 'nonexisting', " + "which is not an attribute of 'admin_checks.Album'.", hint=None, obj=RawIdNonexistingAdmin, id='admin.E002', diff --git a/tests/admin_filters/models.py b/tests/admin_filters/models.py index 9f89809349..40f25d2f30 100644 --- a/tests/admin_filters/models.py +++ b/tests/admin_filters/models.py @@ -20,10 +20,16 @@ class Book(models.Model): related_name='books_authored', blank=True, null=True, ) - contributors = models.ManyToManyField(User, verbose_name="Verbose Contributors", related_name='books_contributed', blank=True) + contributors = models.ManyToManyField( + User, + verbose_name="Verbose Contributors", + related_name='books_contributed', + blank=True, + ) is_best_seller = models.NullBooleanField(default=0) date_registered = models.DateField(null=True) - no = models.IntegerField(verbose_name='number', blank=True, null=True) # This field is intentionally 2 characters long. See #16080. + # This field name is intentionally 2 characters long (#16080). + no = models.IntegerField(verbose_name='number', blank=True, null=True) def __str__(self): return self.title diff --git a/tests/admin_filters/tests.py b/tests/admin_filters/tests.py index 5a230cd983..f17928e4b1 100644 --- a/tests/admin_filters/tests.py +++ b/tests/admin_filters/tests.py @@ -129,11 +129,25 @@ class BookAdmin(ModelAdmin): class BookAdminWithTupleBooleanFilter(BookAdmin): - list_filter = ('year', 'author', 'contributors', ('is_best_seller', BooleanFieldListFilter), 'date_registered', 'no') + list_filter = ( + 'year', + 'author', + 'contributors', + ('is_best_seller', BooleanFieldListFilter), + 'date_registered', + 'no', + ) class BookAdminWithUnderscoreLookupAndTuple(BookAdmin): - list_filter = ('year', ('author__email', AllValuesFieldListFilter), 'contributors', 'is_best_seller', 'date_registered', 'no') + list_filter = ( + 'year', + ('author__email', AllValuesFieldListFilter), + 'contributors', + 'is_best_seller', + 'date_registered', + 'no', + ) class BookAdminWithCustomQueryset(ModelAdmin): @@ -231,10 +245,22 @@ class ListFiltersTests(TestCase): self.lisa = User.objects.create_user('lisa', 'lisa@example.com') # Books - self.djangonaut_book = Book.objects.create(title='Djangonaut: an art of living', year=2009, author=self.alfred, is_best_seller=True, date_registered=self.today) - self.bio_book = Book.objects.create(title='Django: a biography', year=1999, author=self.alfred, is_best_seller=False, no=207) - self.django_book = Book.objects.create(title='The Django Book', year=None, author=self.bob, is_best_seller=None, date_registered=self.today, no=103) - self.gipsy_book = Book.objects.create(title='Gipsy guitar for dummies', year=2002, is_best_seller=True, date_registered=self.one_week_ago) + self.djangonaut_book = Book.objects.create( + title='Djangonaut: an art of living', year=2009, + author=self.alfred, is_best_seller=True, date_registered=self.today, + ) + self.bio_book = Book.objects.create( + title='Django: a biography', year=1999, author=self.alfred, + is_best_seller=False, no=207, + ) + self.django_book = Book.objects.create( + title='The Django Book', year=None, author=self.bob, + is_best_seller=None, date_registered=self.today, no=103, + ) + self.gipsy_book = Book.objects.create( + title='Gipsy guitar for dummies', year=2002, is_best_seller=True, + date_registered=self.one_week_ago, + ) self.gipsy_book.contributors = [self.bob, self.lisa] self.gipsy_book.save() @@ -247,9 +273,13 @@ class ListFiltersTests(TestCase): self.jack = Employee.objects.create(name='Jack Red', department=self.design) def get_changelist(self, request, model, modeladmin): - return ChangeList(request, model, modeladmin.list_display, modeladmin.list_display_links, - modeladmin.list_filter, modeladmin.date_hierarchy, modeladmin.search_fields, - modeladmin.list_select_related, modeladmin.list_per_page, modeladmin.list_max_show_all, modeladmin.list_editable, modeladmin) + return ChangeList( + request, model, modeladmin.list_display, + modeladmin.list_display_links, modeladmin.list_filter, + modeladmin.date_hierarchy, modeladmin.search_fields, + modeladmin.list_select_related, modeladmin.list_per_page, + modeladmin.list_max_show_all, modeladmin.list_editable, modeladmin, + ) def test_datefieldlistfilter(self): modeladmin = BookAdmin(Book, site) @@ -730,7 +760,10 @@ class ListFiltersTests(TestCase): choices = list(filterspec.choices(changelist)) self.assertEqual(choices[3]['display'], 'the 2000\'s') self.assertEqual(choices[3]['selected'], True) - self.assertEqual(choices[3]['query_string'], '?author__id__exact=%s&publication-decade=the+00s' % self.alfred.pk) + self.assertEqual( + choices[3]['query_string'], + '?author__id__exact=%s&publication-decade=the+00s' % self.alfred.pk + ) filterspec = changelist.get_filters(request)[0][0] self.assertEqual(force_text(filterspec.title), 'Verbose Author') diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py index 98d37a7e24..e5e4a66a3b 100644 --- a/tests/admin_inlines/tests.py +++ b/tests/admin_inlines/tests.py @@ -114,7 +114,11 @@ class TestInline(TestDataMixin, TestCase): } response = self.client.post(reverse('admin:admin_inlines_titlecollection_add'), data) # Here colspan is "4": two fields (title1 and title2), one hidden field and the delete checkbox. - self.assertContains(response, '') + self.assertContains( + response, + '' + ) def test_no_parent_callable_lookup(self): """Admin inline `readonly_field` shouldn't invoke parent ModelAdmin callable""" @@ -143,10 +147,24 @@ class TestInline(TestDataMixin, TestCase): """ response = self.client.get(reverse('admin:admin_inlines_holder4_add')) self.assertContains(response, '

Awesome stacked help text is awesome.

', 4) - self.assertContains(response, '(Awesome tabular help text is awesome.)', 1) + self.assertContains( + response, + '', + 1 + ) # ReadOnly fields response = self.client.get(reverse('admin:admin_inlines_capofamiglia_add')) - self.assertContains(response, '(Help text for ReadOnlyInline)', 1) + self.assertContains( + response, + '', + 1 + ) def test_inline_hidden_field_no_column(self): """#18263 -- Make sure hidden fields don't get a column in tabular inlines""" @@ -228,13 +246,17 @@ class TestInline(TestDataMixin, TestCase): def test_custom_get_extra_form(self): bt_head = BinaryTree.objects.create(name="Tree Head") BinaryTree.objects.create(name="First Child", parent=bt_head) - # The maximum number of forms should respect 'get_max_num' on the # ModelAdmin - max_forms_input = '' + max_forms_input = ( + '' + ) # The total number of forms will remain the same in either case - total_forms_hidden = '' - + total_forms_hidden = ( + '' + ) response = self.client.get(reverse('admin:admin_inlines_binarytree_add')) self.assertContains(response, max_forms_input % 3) self.assertContains(response, total_forms_hidden) @@ -254,10 +276,14 @@ class TestInline(TestDataMixin, TestCase): modeladmin = ModelAdmin(BinaryTree, admin_site) modeladmin.inlines = [MinNumInline] - - min_forms = '' - total_forms = '' - + min_forms = ( + '' + ) + total_forms = ( + '' + ) request = self.factory.get(reverse('admin:admin_inlines_binarytree_add')) request.user = User(username='super', is_superuser=True) response = modeladmin.changeform_view(request) @@ -282,10 +308,14 @@ class TestInline(TestDataMixin, TestCase): modeladmin = ModelAdmin(BinaryTree, admin_site) modeladmin.inlines = [MinNumInline] - - min_forms = '' - total_forms = '' - + min_forms = ( + '' + ) + total_forms = ( + '' + ) request = self.factory.get(reverse('admin:admin_inlines_binarytree_add')) request.user = User(username='super', is_superuser=True) response = modeladmin.changeform_view(request) @@ -300,21 +330,33 @@ class TestInline(TestDataMixin, TestCase): def test_inline_nonauto_noneditable_pk(self): response = self.client.get(reverse('admin:admin_inlines_author_add')) - self.assertContains(response, - '', - html=True) - self.assertContains(response, - '', - html=True) + self.assertContains( + response, + '', + html=True + ) + self.assertContains( + response, + '', + html=True + ) def test_inline_editable_pk(self): response = self.client.get(reverse('admin:admin_inlines_author_add')) - self.assertContains(response, - '', - html=True, count=1) - self.assertContains(response, - '', - html=True, count=1) + self.assertContains( + response, + '', + html=True, count=1 + ) + self.assertContains( + response, + '', + html=True, count=1 + ) def test_stacked_inline_edit_form_contains_has_original_class(self): holder = Holder.objects.create(dummy=1) @@ -585,8 +627,12 @@ class TestInlinePermissions(TestCase): self.assertContains(response, 'Add another Author\\u002Dbook relationship') self.assertContains(response, '', html=True) - self.assertContains(response, '' % self.author_book_auto_m2m_intermediate_id, html=True) + self.assertContains( + response, + '' % self.author_book_auto_m2m_intermediate_id, + html=True + ) self.assertContains(response, 'id="id_Author_books-0-DELETE"') def test_inline_change_fk_add_perm(self): @@ -597,8 +643,12 @@ class TestInlinePermissions(TestCase): self.assertContains(response, '

Inner2s

') self.assertContains(response, 'Add another Inner2') # 3 extra forms only, not the existing instance form - self.assertContains(response, '', html=True) + self.assertContains( + response, + '', + html=True + ) self.assertNotContains(response, '' % self.inner2_id, html=True) diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index 397856912e..4e976d89fd 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -964,21 +964,36 @@ class ManageAlternateSettings(AdminScriptTestCase): "alternate: manage.py can execute user commands if settings are provided as argument" args = ['noargs_command', '--settings=alternate_settings'] out, err = self.run_manage(args) - self.assertOutput(out, "EXECUTE: noargs_command options=[('no_color', False), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + "EXECUTE: noargs_command options=[('no_color', False), " + "('pythonpath', None), ('settings', 'alternate_settings'), " + "('traceback', False), ('verbosity', 1)]" + ) self.assertNoOutput(err) def test_custom_command_with_environment(self): "alternate: manage.py can execute user commands if settings are provided in environment" args = ['noargs_command'] out, err = self.run_manage(args, 'alternate_settings') - self.assertOutput(out, "EXECUTE: noargs_command options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + "EXECUTE: noargs_command options=[('no_color', False), " + "('pythonpath', None), ('settings', None), ('traceback', False), " + "('verbosity', 1)]" + ) self.assertNoOutput(err) def test_custom_command_output_color(self): "alternate: manage.py output syntax color can be deactivated with the `--no-color` option" args = ['noargs_command', '--no-color', '--settings=alternate_settings'] out, err = self.run_manage(args) - self.assertOutput(out, "EXECUTE: noargs_command options=[('no_color', True), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + "EXECUTE: noargs_command options=[('no_color', True), " + "('pythonpath', None), ('settings', 'alternate_settings'), " + "('traceback', False), ('verbosity', 1)]" + ) self.assertNoOutput(err) @@ -1660,7 +1675,12 @@ class CommandTypes(AdminScriptTestCase): args = ['noargs_command'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE: noargs_command options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + "EXECUTE: noargs_command options=[('no_color', False), " + "('pythonpath', None), ('settings', None), ('traceback', False), " + "('verbosity', 1)]" + ) def test_noargs_with_args(self): "NoArg Commands raise an error if an argument is provided" @@ -1674,7 +1694,11 @@ class CommandTypes(AdminScriptTestCase): out, err = self.run_manage(args) self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:AppCommand name=django.contrib.auth, options=") - self.assertOutput(out, ", options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + ", options=[('no_color', False), ('pythonpath', None), " + "('settings', None), ('traceback', False), ('verbosity', 1)]" + ) def test_app_command_no_apps(self): "User AppCommands raise an error when no app name is provided" @@ -1688,9 +1712,17 @@ class CommandTypes(AdminScriptTestCase): out, err = self.run_manage(args) self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:AppCommand name=django.contrib.auth, options=") - self.assertOutput(out, ", options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + ", options=[('no_color', False), ('pythonpath', None), " + "('settings', None), ('traceback', False), ('verbosity', 1)]" + ) self.assertOutput(out, "EXECUTE:AppCommand name=django.contrib.contenttypes, options=") - self.assertOutput(out, ", options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + ", options=[('no_color', False), ('pythonpath', None), " + "('settings', None), ('traceback', False), ('verbosity', 1)]" + ) def test_app_command_invalid_app_label(self): "User AppCommands can execute when a single app name is provided" @@ -1709,7 +1741,11 @@ class CommandTypes(AdminScriptTestCase): args = ['label_command', 'testlabel'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), " + "('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]" + ) def test_label_command_no_label(self): "User LabelCommands raise an error if no label is provided" @@ -1722,8 +1758,16 @@ class CommandTypes(AdminScriptTestCase): args = ['label_command', 'testlabel', 'anotherlabel'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") - self.assertOutput(out, "EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]") + self.assertOutput( + out, + "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), " + "('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]" + ) + self.assertOutput( + out, + "EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), " + "('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]" + ) class Discovery(SimpleTestCase): @@ -1794,7 +1838,13 @@ class ArgumentOrder(AdminScriptTestCase): def _test(self, args, option_b="'2'"): out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('option_a', 'x'), ('option_b', %s), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', False), ('verbosity', 1)]" % option_b) + self.assertOutput( + out, + "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), " + "('option_a', 'x'), ('option_b', %s), ('option_c', '3'), " + "('pythonpath', None), ('settings', 'alternate_settings'), " + "('traceback', False), ('verbosity', 1)]" % option_b + ) @override_settings(ROOT_URLCONF='admin_scripts.urls') @@ -1907,7 +1957,10 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase): self.assertTrue(os.path.exists(os.path.join(testproject_dir, 'run.py'))) def test_custom_project_template_from_tarball_by_url(self): - "Make sure the startproject management command is able to use a different project template from a tarball via a url" + """ + The startproject management command is able to use a different project + template from a tarball via a URL. + """ template_url = '%s/custom_templates/project_template.tgz' % self.live_server_url args = ['startproject', '--template', template_url, 'urltestproject'] @@ -1971,7 +2024,11 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase): self.write_settings('alternate_settings.py') self.addCleanup(self.remove_settings, 'alternate_settings.py') template_path = os.path.join(custom_templates_dir, 'project_template') - args = ['custom_startproject', '--template', template_path, 'another_project', 'project_dir', '--extra', '<&>', '--settings=alternate_settings'] + args = [ + 'custom_startproject', '--template', template_path, + 'another_project', 'project_dir', '--extra', '<&>', + '--settings=alternate_settings', + ] testproject_dir = os.path.join(self.test_dir, 'project_dir') os.mkdir(testproject_dir) self.addCleanup(shutil.rmtree, testproject_dir) @@ -1996,7 +2053,10 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase): self.assertFalse(os.path.exists(testproject_dir)) def test_custom_project_template_with_non_ascii_templates(self): - "Ticket 18091: Make sure the startproject management command is able to render templates with non-ASCII content" + """ + The startproject management command is able to render templates with + non-ASCII content. + """ template_path = os.path.join(custom_templates_dir, 'project_template') args = ['startproject', '--template', template_path, '--extension=txt', 'customtestproject'] testproject_dir = os.path.join(self.test_dir, 'customtestproject') diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index 0104181d96..ca114680d0 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -587,7 +587,9 @@ class PluggableSearchPersonAdmin(admin.ModelAdmin): search_fields = ('name',) def get_search_results(self, request, queryset, search_term): - queryset, use_distinct = super(PluggableSearchPersonAdmin, self).get_search_results(request, queryset, search_term) + queryset, use_distinct = super(PluggableSearchPersonAdmin, self).get_search_results( + request, queryset, search_term + ) try: search_term_as_int = int(search_term) queryset |= self.model.objects.filter(age=search_term_as_int) diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index fbeca604d4..87d6f86ae4 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -300,7 +300,8 @@ class AdminViewBasicTest(AdminViewBasicTestCase): """ A smoke test to ensure POST on edit_view works. """ - response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), self.inline_post_data) + url = reverse('admin:admin_views_section_change', args=(self.s1.pk,)) + response = self.client.post(url, self.inline_post_data) self.assertEqual(response.status_code, 302) # redirect somewhere def test_edit_save_as(self): @@ -600,7 +601,10 @@ class AdminViewBasicTest(AdminViewBasicTestCase): link1 = reverse('admin:admin_views_fabric_change', args=(self.fab1.pk,)) link2 = reverse('admin:admin_views_fabric_change', args=(self.fab2.pk,)) response = self.client.get(reverse('admin:admin_views_fabric_changelist')) - fail_msg = "Changelist table isn't showing the right human-readable values set by a model field 'choices' option named group." + fail_msg = ( + "Changelist table isn't showing the right human-readable values " + "set by a model field 'choices' option named group." + ) self.assertContains(response, 'Horizontal' % link1, msg_prefix=fail_msg, html=True) self.assertContains(response, 'Vertical' % link2, msg_prefix=fail_msg, html=True) @@ -610,7 +614,10 @@ class AdminViewBasicTest(AdminViewBasicTestCase): been used in the choices option of a model field. """ response = self.client.get(reverse('admin:admin_views_fabric_changelist')) - fail_msg = "Changelist filter isn't showing options contained inside a model field 'choices' option named group." + fail_msg = ( + "Changelist filter isn't showing options contained inside a model " + "field 'choices' option named group." + ) self.assertContains(response, '
') self.assertContains(response, 'Horizontal', msg_prefix=fail_msg, html=True) @@ -684,7 +691,8 @@ class AdminViewBasicTest(AdminViewBasicTestCase): def test_disallowed_to_field(self): with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls: - response = self.client.get(reverse('admin:admin_views_section_changelist'), {TO_FIELD_VAR: 'missing_field'}) + url = reverse('admin:admin_views_section_changelist') + response = self.client.get(url, {TO_FIELD_VAR: 'missing_field'}) self.assertEqual(response.status_code, 400) self.assertEqual(len(calls), 1) @@ -726,12 +734,14 @@ class AdminViewBasicTest(AdminViewBasicTestCase): section = Section.objects.create() with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls: - response = self.client.post(reverse('admin:admin_views_section_change', args=(section.pk,)), {TO_FIELD_VAR: 'name'}) + url = reverse('admin:admin_views_section_change', args=(section.pk,)) + response = self.client.post(url, {TO_FIELD_VAR: 'name'}) self.assertEqual(response.status_code, 400) self.assertEqual(len(calls), 1) with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls: - response = self.client.post(reverse('admin:admin_views_section_delete', args=(section.pk,)), {TO_FIELD_VAR: 'name'}) + url = reverse('admin:admin_views_section_delete', args=(section.pk,)) + response = self.client.post(url, {TO_FIELD_VAR: 'name'}) self.assertEqual(response.status_code, 400) self.assertEqual(len(calls), 1) @@ -742,7 +752,8 @@ class AdminViewBasicTest(AdminViewBasicTestCase): can break. """ # Filters should be allowed if they are defined on a ForeignKey pointing to this model - response = self.client.get("%s?leader__name=Palin&leader__age=27" % reverse('admin:admin_views_inquisition_changelist')) + url = "%s?leader__name=Palin&leader__age=27" % reverse('admin:admin_views_inquisition_changelist') + response = self.client.get(url) self.assertEqual(response.status_code, 200) def test_popup_dismiss_related(self): @@ -1787,24 +1798,24 @@ class AdminViewPermissionsTest(TestCase): rl2 = RowLevelChangePermissionModel.objects.create(name="even id") for login_dict in [self.super_login, self.changeuser_login, self.adduser_login, self.deleteuser_login]: self.client.post(login_url, login_dict) - response = self.client.get(reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl1.pk,))) + url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl1.pk,)) + response = self.client.get(url) self.assertEqual(response.status_code, 403) - response = self.client.get(reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl2.pk,))) + url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl2.pk,)) + response = self.client.get(url) self.assertEqual(response.status_code, 200) self.client.get(reverse('admin:logout')) for login_dict in [self.joepublic_login, self.no_username_login]: self.client.post(login_url, login_dict) - response = self.client.get( - reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl1.pk,)), follow=True - ) + url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl1.pk,)) + response = self.client.get(url, follow=True) self.assertEqual(response.status_code, 200) self.assertContains(response, 'login-form') - response = self.client.get( - reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl2.pk,)), follow=True - ) + url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl2.pk,)) + response = self.client.get(url, follow=True) self.assertEqual(response.status_code, 200) self.assertContains(response, 'login-form') @@ -2118,11 +2129,15 @@ class AdminViewDeletedObjectsTest(TestCase): Objects should be nested to display the relationships that cause them to be scheduled for deletion. """ - pattern = re.compile(force_bytes( - r'
  • Plot: World Domination\s*
      \s*
    • Plot details: almost finished' % ( - reverse('admin:admin_views_plot_change', args=(self.pl1.pk,)), - reverse('admin:admin_views_plotdetails_change', args=(self.pd1.pk,))) - )) + pattern = re.compile( + force_bytes( + r'
    • Plot: World Domination\s*
        \s*' + r'
      • Plot details: almost finished' % ( + reverse('admin:admin_views_plot_change', args=(self.pl1.pk,)), + reverse('admin:admin_views_plotdetails_change', args=(self.pd1.pk,)), + ) + ) + ) response = self.client.get(reverse('admin:admin_views_villain_delete', args=(self.v1.pk,))) six.assertRegex(self, response.content, pattern) @@ -2210,7 +2225,9 @@ class AdminViewDeletedObjectsTest(TestCase): """ should_contain = [ '
      • Villain: Bob' % reverse('admin:admin_views_villain_change', args=(self.sv1.pk,)), - '
      • Super villain: Bob' % reverse('admin:admin_views_supervillain_change', args=(self.sv1.pk,)), + '
      • Super villain: Bob' % reverse( + 'admin:admin_views_supervillain_change', args=(self.sv1.pk,) + ), '
      • Secret hideout: floating castle', '
      • Super secret hideout: super floating castle!', ] @@ -2324,7 +2341,10 @@ class AdminViewStringPrimaryKeyTest(TestCase): content='

        Newest content

        ', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1 ) cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title') - cls.pk = """abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 -_.!~*'() ;/?:@&=+$, <>#%" {}|\^[]`""" + cls.pk = ( + "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 " + """-_.!~*'() ;/?:@&=+$, <>#%" {}|\^[]`""" + ) cls.m1 = ModelWithStringPrimaryKey.objects.create(string_pk=cls.pk) content_type_pk = ContentType.objects.get_for_model(ModelWithStringPrimaryKey).pk LogEntry.objects.log_action(100, content_type_pk, cls.pk, cls.pk, 2, change_message='Changed something') @@ -2389,7 +2409,10 @@ class AdminViewStringPrimaryKeyTest(TestCase): counted_presence_after) def test_logentry_get_admin_url(self): - "LogEntry.get_admin_url returns a URL to edit the entry's object or None for non-existent (possibly deleted) models" + """ + LogEntry.get_admin_url returns a URL to edit the entry's object or + None for non-existent (possibly deleted) models. + """ log_entry_model = "modelwithstringprimarykey" # capitalized in Recent Actions logentry = LogEntry.objects.get(content_type__model__iexact=log_entry_model) desired_admin_url = reverse('admin:admin_views_modelwithstringprimarykey_change', args=(quote(self.pk),)) @@ -2418,7 +2441,8 @@ class AdminViewStringPrimaryKeyTest(TestCase): def test_deleteconfirmation_link(self): "The link from the delete confirmation page referring back to the changeform of the object should be quoted" - response = self.client.get(reverse('admin:admin_views_modelwithstringprimarykey_delete', args=(quote(self.pk),))) + url = reverse('admin:admin_views_modelwithstringprimarykey_delete', args=(quote(self.pk),)) + response = self.client.get(url) # this URL now comes through reverse(), thus url quoting and iri_to_uri encoding change_url = reverse( 'admin:admin_views_modelwithstringprimarykey_change', args=('__fk__',) @@ -3028,11 +3052,22 @@ class AdminViewListEditable(TestCase): Refs #12475. """ story1 = Story.objects.create(title='The adventures of Guido', content='Once upon a time in Djangoland...') - story2 = Story.objects.create(title='Crouching Tiger, Hidden Python', content='The Python was sneaking into...') + story2 = Story.objects.create( + title='Crouching Tiger, Hidden Python', + content='The Python was sneaking into...', + ) response = self.client.get(reverse('admin:admin_views_story_changelist')) - self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table. + # Only one hidden field, in a separate place than the table. + self.assertContains(response, 'id="id_form-0-id"', 1) self.assertContains(response, 'id="id_form-1-id"', 1) - self.assertContains(response, '
        \n\n
        ' % (story2.id, story1.id), html=True) + self.assertContains( + response, + '
        \n' + '' + '\n
        ' + % (story2.id, story1.id), + html=True + ) self.assertContains(response, '%d' % story1.id, 1) self.assertContains(response, '%d' % story2.id, 1) @@ -3041,14 +3076,28 @@ class AdminViewListEditable(TestCase): referenced in list_display_links. Refs #12475. """ - story1 = OtherStory.objects.create(title='The adventures of Guido', content='Once upon a time in Djangoland...') - story2 = OtherStory.objects.create(title='Crouching Tiger, Hidden Python', content='The Python was sneaking into...') + story1 = OtherStory.objects.create( + title='The adventures of Guido', + content='Once upon a time in Djangoland...', + ) + story2 = OtherStory.objects.create( + title='Crouching Tiger, Hidden Python', + content='The Python was sneaking into...', + ) link1 = reverse('admin:admin_views_otherstory_change', args=(story1.pk,)) link2 = reverse('admin:admin_views_otherstory_change', args=(story2.pk,)) response = self.client.get(reverse('admin:admin_views_otherstory_changelist')) - self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table. + # Only one hidden field, in a separate place than the table. + self.assertContains(response, 'id="id_form-0-id"', 1) self.assertContains(response, 'id="id_form-1-id"', 1) - self.assertContains(response, '
        \n\n
        ' % (story2.id, story1.id), html=True) + self.assertContains( + response, + '
        \n' + '' + '\n
        ' + % (story2.id, story1.id), + html=True + ) self.assertContains(response, '%d' % (link1, story1.id), 1) self.assertContains(response, '%d' % (link2, story2.id), 1) @@ -3850,9 +3899,11 @@ class AdminCustomQuerysetTest(TestCase): # Message should contain non-ugly model verbose name. The ugly(!) # instance representation is set by six.text_type() self.assertContains( - response, - '
      • The short message "ShortMessage_Deferred_timestamp object" was changed successfully.
      • ', - html=True + response, ( + '
      • The short message ' + '"ShortMessage_Deferred_timestamp object" was ' + 'changed successfully.
      • ' + ), html=True ) def test_edit_model_modeladmin_only_qs(self): @@ -4462,9 +4513,15 @@ class SeleniumAdminViewsFirefoxTests(AdminSeleniumWebDriverTestCase): # Initial inline self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-pubdate').send_keys('2011-12-17') self.get_select_option('#id_relatedprepopulated_set-0-status', 'option one').click() - self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-name').send_keys(' here is a sŤāÇkeð inline ! ') - slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug1').get_attribute('value') - slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug2').get_attribute('value') + self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-0-name' + ).send_keys(' here is a sŤāÇkeð inline ! ') + slug1 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-0-slug1' + ).get_attribute('value') + slug2 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-0-slug2' + ).get_attribute('value') self.assertEqual(slug1, 'here-stacked-inline-2011-12-17') self.assertEqual(slug2, 'option-one-here-stacked-inline') @@ -4472,19 +4529,34 @@ class SeleniumAdminViewsFirefoxTests(AdminSeleniumWebDriverTestCase): self.selenium.find_elements_by_link_text('Add another Related prepopulated')[0].click() self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-pubdate').send_keys('1999-01-25') self.get_select_option('#id_relatedprepopulated_set-1-status', 'option two').click() - self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-name').send_keys(' now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog text... ') - slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug1').get_attribute('value') - slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug2').get_attribute('value') - self.assertEqual(slug1, 'now-you-have-another-stacked-inline-very-loooooooo') # 50 characters maximum for slug1 field - self.assertEqual(slug2, 'option-two-now-you-have-another-stacked-inline-very-looooooo') # 60 characters maximum for slug2 field + self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-name').send_keys( + ' now you haVe anöther sŤāÇkeð inline with a very ... ' + 'loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog text... ' + ) + slug1 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-1-slug1' + ).get_attribute('value') + slug2 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-1-slug2' + ).get_attribute('value') + # 50 characters maximum for slug1 field + self.assertEqual(slug1, 'now-you-have-another-stacked-inline-very-loooooooo') + # 60 characters maximum for slug2 field + self.assertEqual(slug2, 'option-two-now-you-have-another-stacked-inline-very-looooooo') # Tabular inlines ---------------------------------------------------- # Initial inline self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-pubdate').send_keys('1234-12-07') self.get_select_option('#id_relatedprepopulated_set-2-0-status', 'option two').click() - self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-name').send_keys('And now, with a tÃbűlaŘ inline !!!') - slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug1').get_attribute('value') - slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug2').get_attribute('value') + self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-2-0-name' + ).send_keys('And now, with a tÃbűlaŘ inline !!!') + slug1 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-2-0-slug1' + ).get_attribute('value') + slug2 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-2-0-slug2' + ).get_attribute('value') self.assertEqual(slug1, 'and-now-tabular-inline-1234-12-07') self.assertEqual(slug2, 'option-two-and-now-tabular-inline') @@ -4492,9 +4564,15 @@ class SeleniumAdminViewsFirefoxTests(AdminSeleniumWebDriverTestCase): self.selenium.find_elements_by_link_text('Add another Related prepopulated')[1].click() self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-pubdate').send_keys('1981-08-22') self.get_select_option('#id_relatedprepopulated_set-2-1-status', 'option one').click() - self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-name').send_keys('a tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters') - slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug1').get_attribute('value') - slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug2').get_attribute('value') + self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-name').send_keys( + 'a tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters' + ) + slug1 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-2-1-slug1' + ).get_attribute('value') + slug2 = self.selenium.find_element_by_css_selector( + '#id_relatedprepopulated_set-2-1-slug2' + ).get_attribute('value') self.assertEqual(slug1, 'tabular-inline-ignored-characters-1981-08-22') self.assertEqual(slug2, 'option-one-tabular-inline-ignored-characters') @@ -4518,7 +4596,8 @@ class SeleniumAdminViewsFirefoxTests(AdminSeleniumWebDriverTestCase): slug2='option-one-here-stacked-inline', ) RelatedPrepopulated.objects.get( - name=' now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooo', # 75 characters in name field + # 75 characters in name field + name=' now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooo', pubdate='1999-01-25', status='option two', slug1='now-you-have-another-stacked-inline-very-loooooooo', @@ -4713,9 +4792,21 @@ class ReadonlyTest(TestCase): self.assertContains(response, '
        ') self.assertContains(response, '
        ') self.assertContains(response, '

        ', 3) - self.assertContains(response, '

        Some help text for the title (with unicode ŠĐĆŽćžšđ)

        ', html=True) - self.assertContains(response, '

        Some help text for the content (with unicode ŠĐĆŽćžšđ)

        ', html=True) - self.assertContains(response, '

        Some help text for the date (with unicode ŠĐĆŽćžšđ)

        ', html=True) + self.assertContains( + response, + '

        Some help text for the title (with unicode ŠĐĆŽćžšđ)

        ', + html=True + ) + self.assertContains( + response, + '

        Some help text for the content (with unicode ŠĐĆŽćžšđ)

        ', + html=True + ) + self.assertContains( + response, + '

        Some help text for the date (with unicode ŠĐĆŽćžšđ)

        ', + html=True + ) p = Post.objects.create(title="I worked on readonly_fields", content="Its good stuff") response = self.client.get(reverse('admin:admin_views_post_change', args=(p.pk,))) @@ -5741,20 +5832,30 @@ class AdminKeepChangeListFiltersTests(TestCase): # Test equality. change_user_url = reverse('admin:auth_user_change', args=(self.u5.pk,)) self.assertURLEqual( - 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(change_user_url), - 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(change_user_url) + 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format( + change_user_url + ), + 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format( + change_user_url + ) ) # Test inequality. with self.assertRaises(AssertionError): self.assertURLEqual( - 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(change_user_url), - 'http://testserver{}?_changelist_filters=is_staff__exact%3D1%26is_superuser__exact%3D1'.format(change_user_url) + 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format( + change_user_url + ), + 'http://testserver{}?_changelist_filters=is_staff__exact%3D1%26is_superuser__exact%3D1'.format( + change_user_url + ) ) # Ignore scheme and host. self.assertURLEqual( - 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(change_user_url), + 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format( + change_user_url + ), '{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(change_user_url) ) diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py index efdc7eab93..8572db508a 100644 --- a/tests/admin_widgets/tests.py +++ b/tests/admin_widgets/tests.py @@ -189,7 +189,10 @@ class AdminFormfieldForDBFieldTests(SimpleTestCase): filter_vertical=['companies']) ma = AdvisorAdmin(models.Advisor, admin.site) f = ma.formfield_for_dbfield(models.Advisor._meta.get_field('companies'), request=None) - self.assertEqual(six.text_type(f.help_text), 'Hold down "Control", or "Command" on a Mac, to select more than one.') + self.assertEqual( + six.text_type(f.help_text), + 'Hold down "Control", or "Command" on a Mac, to select more than one.' + ) @override_settings(PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'], @@ -327,7 +330,11 @@ class AdminSplitDateTimeWidgetTest(SimpleTestCase): w = widgets.AdminSplitDateTime() self.assertHTMLEqual( w.render('test', datetime(2007, 12, 1, 9, 30)), - '

        Date:
        Time:

        ', + '

        ' + 'Date:
        ' + 'Time:

        ' ) def test_localization(self): @@ -337,7 +344,11 @@ class AdminSplitDateTimeWidgetTest(SimpleTestCase): w.is_localized = True self.assertHTMLEqual( w.render('test', datetime(2007, 12, 1, 9, 30)), - '

        Datum:
        Zeit:

        ', + '

        ' + 'Datum:
        ' + 'Zeit:

        ' ) @@ -350,14 +361,20 @@ class AdminURLWidgetTest(SimpleTestCase): ) self.assertHTMLEqual( w.render('test', 'http://example.com'), - '

        Currently:http://example.com
        Change:

        ' + '

        Currently:' + 'http://example.com
        ' + 'Change:

        ' ) def test_render_idn(self): w = widgets.AdminURLFieldWidget() self.assertHTMLEqual( w.render('test', 'http://example-äüö.com'), - '

        Currently: http://example-äüö.com
        Change:

        ' + '

        Currently: ' + 'http://example-äüö.com
        ' + 'Change:

        ' ) def test_render_quoting(self): @@ -366,15 +383,29 @@ class AdminURLWidgetTest(SimpleTestCase): w = widgets.AdminURLFieldWidget() self.assertEqual( w.render('test', 'http://example.com/some text'), - '

        Currently: http://example.com/<sometag>some text</sometag>
        Change:

        ' + '

        Currently: ' + '' + 'http://example.com/<sometag>some text</sometag>
        ' + 'Change:

        ' ) self.assertEqual( w.render('test', 'http://example-äüö.com/some text'), - '

        Currently: http://example-äüö.com/<sometag>some text</sometag>
        Change:

        ' + '

        Currently: ' + '' + 'http://example-äüö.com/<sometag>some text</sometag>
        ' + 'Change:

        ' ) self.assertEqual( w.render('test', 'http://www.example.com/%C3%A4">"'), - '

        Currently: http://www.example.com/%C3%A4"><script>alert("XSS!")</script>"
        Change:

        ' + '

        Currently: ' + '' + 'http://www.example.com/%C3%A4"><script>' + 'alert("XSS!")</script>"
        ' + 'Change:

        ' ) @@ -447,11 +478,12 @@ class ForeignKeyRawIdWidgetTest(TestCase): w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site) self.assertHTMLEqual( - w.render('test', band.pk, attrs={}), ( - '' - '' - ' Linkin Park' - ) % {'bandpk': band.pk} + w.render('test', band.pk, attrs={}), + '' + ' Linkin Park' + % {'bandpk': band.pk} ) def test_relations_to_non_primary_key(self): @@ -465,11 +497,12 @@ class ForeignKeyRawIdWidgetTest(TestCase): rel = models.Inventory._meta.get_field('parent').remote_field w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site) self.assertHTMLEqual( - w.render('test', core.parent_id, attrs={}), ( - '' - '' - ' Apple' - ) + w.render('test', core.parent_id, attrs={}), + '' + '' + ' Apple' ) def test_fk_related_model_not_in_admin(self): @@ -482,7 +515,9 @@ class ForeignKeyRawIdWidgetTest(TestCase): w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site) self.assertHTMLEqual( w.render('honeycomb_widget', big_honeycomb.pk, attrs={}), - ' Honeycomb object' % {'hcombpk': big_honeycomb.pk} + '' + ' Honeycomb object' + % {'hcombpk': big_honeycomb.pk} ) def test_fk_to_self_model_not_in_admin(self): @@ -495,7 +530,9 @@ class ForeignKeyRawIdWidgetTest(TestCase): w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site) self.assertHTMLEqual( w.render('individual_widget', subject1.pk, attrs={}), - ' Individual object' % {'subj1pk': subject1.pk} + '' + ' Individual object' + % {'subj1pk': subject1.pk} ) def test_proper_manager_for_label_lookup(self): @@ -510,11 +547,11 @@ class ForeignKeyRawIdWidgetTest(TestCase): barcode=94, name='Child of hidden', parent=hidden ) self.assertHTMLEqual( - w.render('test', child_of_hidden.parent_id, attrs={}), ( - '' - '' - ' Hidden' - ) + w.render('test', child_of_hidden.parent_id, attrs={}), + '' + '' + ' Hidden' ) diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py index ad42aa3d77..1472bd04fd 100644 --- a/tests/aggregation/tests.py +++ b/tests/aggregation/tests.py @@ -307,7 +307,12 @@ class AggregateTestCase(TestCase): ] ) - books = Book.objects.filter(pk=self.b1.pk).annotate(mean_age=Avg('authors__age')).values('pk', 'isbn', 'mean_age') + books = ( + Book.objects + .filter(pk=self.b1.pk) + .annotate(mean_age=Avg('authors__age')) + .values('pk', 'isbn', 'mean_age') + ) self.assertEqual( list(books), [ { @@ -345,7 +350,12 @@ class AggregateTestCase(TestCase): ] ) - books = Book.objects.values("rating").annotate(n_authors=Count("authors__id"), mean_age=Avg("authors__age")).order_by("rating") + books = ( + Book.objects + .values("rating") + .annotate(n_authors=Count("authors__id"), mean_age=Avg("authors__age")) + .order_by("rating") + ) self.assertEqual( list(books), [ { @@ -561,7 +571,12 @@ class AggregateTestCase(TestCase): lambda p: p.name ) - publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1, book__price__lt=Decimal("40.0")).order_by("pk") + publishers = ( + Publisher.objects + .annotate(num_books=Count("book__id")) + .filter(num_books__gt=1, book__price__lt=Decimal("40.0")) + .order_by("pk") + ) self.assertQuerysetEqual( publishers, [ "Apress", @@ -571,7 +586,13 @@ class AggregateTestCase(TestCase): lambda p: p.name, ) - publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk") + publishers = ( + Publisher.objects + .filter(book__price__lt=Decimal("40.0")) + .annotate(num_books=Count("book__id")) + .filter(num_books__gt=1) + .order_by("pk") + ) self.assertQuerysetEqual( publishers, [ "Apress", @@ -628,7 +649,12 @@ class AggregateTestCase(TestCase): lambda b: b.name ) - authors = Author.objects.annotate(num_friends=Count("friends__id", distinct=True)).filter(num_friends=0).order_by("pk") + authors = ( + Author.objects + .annotate(num_friends=Count("friends__id", distinct=True)) + .filter(num_friends=0) + .order_by("pk") + ) self.assertQuerysetEqual( authors, [ "Brad Dayley", @@ -645,7 +671,12 @@ class AggregateTestCase(TestCase): lambda p: p.name ) - publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).annotate(num_books=Count("book__id")).filter(num_books__gt=1) + publishers = ( + Publisher.objects + .filter(book__price__lt=Decimal("40.0")) + .annotate(num_books=Count("book__id")) + .filter(num_books__gt=1) + ) self.assertQuerysetEqual( publishers, [ "Apress", @@ -653,7 +684,11 @@ class AggregateTestCase(TestCase): lambda p: p.name ) - books = Book.objects.annotate(num_authors=Count("authors__id")).filter(authors__name__contains="Norvig", num_authors__gt=1) + books = ( + Book.objects + .annotate(num_authors=Count("authors__id")) + .filter(authors__name__contains="Norvig", num_authors__gt=1) + ) self.assertQuerysetEqual( books, [ "Artificial Intelligence: A Modern Approach", @@ -667,7 +702,12 @@ class AggregateTestCase(TestCase): b.authors.add(a) b.save() - vals = Book.objects.annotate(num_authors=Count("authors__id")).filter(authors__name__contains="Norvig", num_authors__gt=1).aggregate(Avg("rating")) + vals = ( + Book.objects + .annotate(num_authors=Count("authors__id")) + .filter(authors__name__contains="Norvig", num_authors__gt=1) + .aggregate(Avg("rating")) + ) self.assertEqual(vals, {"rating__avg": 4.25}) def test_even_more_aggregate(self): @@ -718,7 +758,12 @@ class AggregateTestCase(TestCase): ) def test_annotate_values_list(self): - books = Book.objects.filter(pk=self.b1.pk).annotate(mean_age=Avg("authors__age")).values_list("pk", "isbn", "mean_age") + books = ( + Book.objects + .filter(pk=self.b1.pk) + .annotate(mean_age=Avg("authors__age")) + .values_list("pk", "isbn", "mean_age") + ) self.assertEqual( list(books), [ (1, "159059725", 34.5), @@ -739,7 +784,12 @@ class AggregateTestCase(TestCase): ] ) - books = Book.objects.filter(pk=self.b1.pk).annotate(mean_age=Avg("authors__age")).values_list("mean_age", flat=True) + books = ( + Book.objects + .filter(pk=self.b1.pk) + .annotate(mean_age=Avg("authors__age")) + .values_list("mean_age", flat=True) + ) self.assertEqual(list(books), [34.5]) books = Book.objects.values_list("price").annotate(count=Count("price")).order_by("-count", "price") diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py index beb87bdb3a..380a33b66d 100644 --- a/tests/aggregation_regress/tests.py +++ b/tests/aggregation_regress/tests.py @@ -319,7 +319,13 @@ class AggregationTests(TestCase): ) # Check that consecutive calls to annotate accumulate in the query - qs = Book.objects.values('price').annotate(oldest=Max('authors__age')).order_by('oldest', 'price').annotate(Max('publisher__num_awards')) + qs = ( + Book.objects + .values('price') + .annotate(oldest=Max('authors__age')) + .order_by('oldest', 'price') + .annotate(Max('publisher__num_awards')) + ) self.assertQuerysetEqual( qs, [ {'price': Decimal("30"), 'oldest': 35, 'publisher__num_awards__max': 3}, @@ -334,7 +340,12 @@ class AggregationTests(TestCase): def test_aggrate_annotation(self): # Aggregates can be composed over annotations. # The return type is derived from the composed aggregate - vals = Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('pages'), Max('price'), Sum('num_authors'), Avg('num_authors')) + vals = ( + Book.objects + .all() + .annotate(num_authors=Count('authors__id')) + .aggregate(Max('pages'), Max('price'), Sum('num_authors'), Avg('num_authors')) + ) self.assertEqual(vals, { 'num_authors__sum': 10, 'num_authors__avg': Approximate(1.666, places=2), @@ -441,18 +452,34 @@ class AggregationTests(TestCase): ) self.assertEqual( - len(Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__lt=3).exclude(num_authors__lt=2)), + len( + Book.objects + .annotate(num_authors=Count('authors')) + .filter(num_authors__lt=3) + .exclude(num_authors__lt=2) + ), 2 ) self.assertEqual( - len(Book.objects.annotate(num_authors=Count('authors')).exclude(num_authors__lt=2).filter(num_authors__lt=3)), + len( + Book.objects + .annotate(num_authors=Count('authors')) + .exclude(num_authors__lt=2) + .filter(num_authors__lt=3) + ), 2 ) def test_aggregate_fexpr(self): # Aggregates can be used with F() expressions # ... where the F() is pushed into the HAVING clause - qs = Publisher.objects.annotate(num_books=Count('book')).filter(num_books__lt=F('num_awards') / 2).order_by('name').values('name', 'num_books', 'num_awards') + qs = ( + Publisher.objects + .annotate(num_books=Count('book')) + .filter(num_books__lt=F('num_awards') / 2) + .order_by('name') + .values('name', 'num_books', 'num_awards') + ) self.assertQuerysetEqual( qs, [ {'num_books': 1, 'name': 'Morgan Kaufmann', 'num_awards': 9}, @@ -461,7 +488,13 @@ class AggregationTests(TestCase): lambda p: p, ) - qs = Publisher.objects.annotate(num_books=Count('book')).exclude(num_books__lt=F('num_awards') / 2).order_by('name').values('name', 'num_books', 'num_awards') + qs = ( + Publisher.objects + .annotate(num_books=Count('book')) + .exclude(num_books__lt=F('num_awards') / 2) + .order_by('name') + .values('name', 'num_books', 'num_awards') + ) self.assertQuerysetEqual( qs, [ {'num_books': 2, 'name': 'Apress', 'num_awards': 3}, @@ -472,7 +505,13 @@ class AggregationTests(TestCase): ) # ... and where the F() references an aggregate - qs = Publisher.objects.annotate(num_books=Count('book')).filter(num_awards__gt=2 * F('num_books')).order_by('name').values('name', 'num_books', 'num_awards') + qs = ( + Publisher.objects + .annotate(num_books=Count('book')) + .filter(num_awards__gt=2 * F('num_books')) + .order_by('name') + .values('name', 'num_books', 'num_awards') + ) self.assertQuerysetEqual( qs, [ {'num_books': 1, 'name': 'Morgan Kaufmann', 'num_awards': 9}, @@ -481,7 +520,13 @@ class AggregationTests(TestCase): lambda p: p, ) - qs = Publisher.objects.annotate(num_books=Count('book')).exclude(num_books__lt=F('num_awards') / 2).order_by('name').values('name', 'num_books', 'num_awards') + qs = ( + Publisher.objects + .annotate(num_books=Count('book')) + .exclude(num_books__lt=F('num_awards') / 2) + .order_by('name') + .values('name', 'num_books', 'num_awards') + ) self.assertQuerysetEqual( qs, [ {'num_books': 2, 'name': 'Apress', 'num_awards': 3}, @@ -493,7 +538,11 @@ class AggregationTests(TestCase): def test_db_col_table(self): # Tests on fields with non-default table and column names. - qs = Clues.objects.values('EntryID__Entry').annotate(Appearances=Count('EntryID'), Distinct_Clues=Count('Clue', distinct=True)) + qs = ( + Clues.objects + .values('EntryID__Entry') + .annotate(Appearances=Count('EntryID'), Distinct_Clues=Count('Clue', distinct=True)) + ) self.assertQuerysetEqual(qs, []) qs = Entries.objects.annotate(clue_count=Count('clues__ID')) @@ -518,17 +567,45 @@ class AggregationTests(TestCase): 0 ) - vals = Book.objects.filter(id__in=[]).aggregate(num_authors=Count('authors'), avg_authors=Avg('authors'), max_authors=Max('authors'), max_price=Max('price'), max_rating=Max('rating')) + vals = ( + Book.objects + .filter(id__in=[]) + .aggregate( + num_authors=Count('authors'), + avg_authors=Avg('authors'), + max_authors=Max('authors'), + max_price=Max('price'), + max_rating=Max('rating'), + ) + ) self.assertEqual( vals, {'max_authors': None, 'max_rating': None, 'num_authors': 0, 'avg_authors': None, 'max_price': None} ) - qs = Publisher.objects.filter(name="Jonno's House of Books").annotate(num_authors=Count('book__authors'), avg_authors=Avg('book__authors'), max_authors=Max('book__authors'), max_price=Max('book__price'), max_rating=Max('book__rating')).values() + qs = ( + Publisher.objects + .filter(name="Jonno's House of Books") + .annotate( + num_authors=Count('book__authors'), + avg_authors=Avg('book__authors'), + max_authors=Max('book__authors'), + max_price=Max('book__price'), + max_rating=Max('book__rating'), + ).values() + ) self.assertQuerysetEqual( - qs, [ - {'max_authors': None, 'name': "Jonno's House of Books", 'num_awards': 0, 'max_price': None, 'num_authors': 0, 'max_rating': None, 'id': self.p5.id, 'avg_authors': None} - ], + qs, + [{ + 'max_authors': None, + 'name': "Jonno's House of Books", + 'num_awards': 0, + 'max_price': None, + 'num_authors': 0, + 'max_rating': None, + 'id': self.p5.id, + 'avg_authors': None, + }], lambda p: p ) @@ -551,10 +628,16 @@ class AggregationTests(TestCase): # Regression for #10127 - Empty select_related() works with annotate qs = Book.objects.filter(rating__lt=4.5).select_related().annotate(Avg('authors__age')) self.assertQuerysetEqual( - qs, [ + qs, + [ ('Artificial Intelligence: A Modern Approach', 51.5, 'Prentice Hall', 'Peter Norvig'), ('Practical Django Projects', 29.0, 'Apress', 'James Bennett'), - ('Python Web Development with Django', Approximate(30.333, places=2), 'Prentice Hall', 'Jeffrey Forcier'), + ( + 'Python Web Development with Django', + Approximate(30.333, places=2), + 'Prentice Hall', + 'Jeffrey Forcier', + ), ('Sams Teach Yourself Django in 24 Hours', 45.0, 'Sams', 'Brad Dayley') ], lambda b: (b.name, b.authors__age__avg, b.publisher.name, b.contact.name) @@ -573,7 +656,13 @@ class AggregationTests(TestCase): lambda b: b ) - qs = Book.objects.extra(select={'pub': 'publisher_id', 'foo': 'pages'}).values('pub').annotate(Count('id')).order_by('pub') + qs = ( + Book.objects + .extra(select={'pub': 'publisher_id', 'foo': 'pages'}) + .values('pub') + .annotate(Count('id')) + .order_by('pub') + ) self.assertQuerysetEqual( qs, [ {'pub': self.p1.id, 'id__count': 2}, @@ -586,7 +675,13 @@ class AggregationTests(TestCase): # Regression for #10182 - Queries with aggregate calls are correctly # realiased when used in a subquery - ids = Book.objects.filter(pages__gt=100).annotate(n_authors=Count('authors')).filter(n_authors__gt=2).order_by('n_authors') + ids = ( + Book.objects + .filter(pages__gt=100) + .annotate(n_authors=Count('authors')) + .filter(n_authors__gt=2) + .order_by('n_authors') + ) self.assertQuerysetEqual( Book.objects.filter(id__in=ids), [ "Python Web Development with Django", @@ -603,14 +698,20 @@ class AggregationTests(TestCase): def test_duplicate_alias(self): # Regression for #11256 - duplicating a default alias raises ValueError. - self.assertRaises(ValueError, Book.objects.all().annotate, Avg('authors__age'), authors__age__avg=Avg('authors__age')) + self.assertRaises( + ValueError, + Book.objects.all().annotate, + Avg('authors__age'), authors__age__avg=Avg('authors__age') + ) def test_field_name_conflict(self): - # Regression for #11256 - providing an aggregate name that conflicts with a field name on the model raises ValueError + # Regression for #11256 - providing an aggregate name + # that conflicts with a field name on the model raises ValueError self.assertRaises(ValueError, Author.objects.annotate, age=Avg('friends__age')) def test_m2m_name_conflict(self): - # Regression for #11256 - providing an aggregate name that conflicts with an m2m name on the model raises ValueError + # Regression for #11256 - providing an aggregate name + # that conflicts with an m2m name on the model raises ValueError self.assertRaises(ValueError, Author.objects.annotate, friends=Count('friends')) def test_values_queryset_non_conflict(self): @@ -636,7 +737,8 @@ class AggregationTests(TestCase): self.assertEqual(results[0]['friends'], 2) def test_reverse_relation_name_conflict(self): - # Regression for #11256 - providing an aggregate name that conflicts with a reverse-related name on the model raises ValueError + # Regression for #11256 - providing an aggregate name + # that conflicts with a reverse-related name on the model raises ValueError self.assertRaises(ValueError, Author.objects.annotate, book_contact_set=Avg('friends__age')) def test_pickle(self): @@ -682,7 +784,13 @@ class AggregationTests(TestCase): # Regression for #10290 - extra selects with parameters can be used for # grouping. - qs = Book.objects.annotate(mean_auth_age=Avg('authors__age')).extra(select={'sheets': '(pages + %s) / %s'}, select_params=[1, 2]).order_by('sheets').values('sheets') + qs = ( + Book.objects + .annotate(mean_auth_age=Avg('authors__age')) + .extra(select={'sheets': '(pages + %s) / %s'}, select_params=[1, 2]) + .order_by('sheets') + .values('sheets') + ) self.assertQuerysetEqual( qs, [ 150, @@ -766,18 +874,26 @@ class AggregationTests(TestCase): qs = HardbackBook.objects.annotate(n_authors=Count('book_ptr__authors')).values('name', 'n_authors') self.assertQuerysetEqual( - qs, [ + qs, + [ {'n_authors': 2, 'name': 'Artificial Intelligence: A Modern Approach'}, - {'n_authors': 1, 'name': 'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp'} + { + 'n_authors': 1, + 'name': 'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp' + } ], lambda h: h ) qs = HardbackBook.objects.annotate(n_authors=Count('authors')).values('name', 'n_authors') self.assertQuerysetEqual( - qs, [ + qs, + [ {'n_authors': 2, 'name': 'Artificial Intelligence: A Modern Approach'}, - {'n_authors': 1, 'name': 'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp'} + { + 'n_authors': 1, + 'name': 'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp' + } ], lambda h: h, ) @@ -871,11 +987,17 @@ class AggregationTests(TestCase): attrgetter("name") ) - qs = Book.objects.annotate(n_authors=Count("authors")).filter( - Q(name="The Definitive Guide to Django: Web Development Done Right") | (Q(name="Artificial Intelligence: A Modern Approach") & Q(n_authors=3)) + qs = ( + Book.objects + .annotate(n_authors=Count("authors")) + .filter( + Q(name="The Definitive Guide to Django: Web Development Done Right") + | (Q(name="Artificial Intelligence: A Modern Approach") & Q(n_authors=3)) + ) ) self.assertQuerysetEqual( - qs, [ + qs, + [ "The Definitive Guide to Django: Web Development Done Right", ], attrgetter("name") diff --git a/tests/auth_tests/test_middleware.py b/tests/auth_tests/test_middleware.py index 44372bce01..e67a89ef26 100644 --- a/tests/auth_tests/test_middleware.py +++ b/tests/auth_tests/test_middleware.py @@ -38,7 +38,8 @@ class TestSessionAuthenticationMiddleware(TestCase): self.assertEqual(session_key, self.request.session.session_key) def test_changed_password_invalidates_session_with_middleware(self): - with self.modify_settings(MIDDLEWARE_CLASSES={'append': ['django.contrib.auth.middleware.SessionAuthenticationMiddleware']}): + with self.modify_settings( + MIDDLEWARE_CLASSES={'append': ['django.contrib.auth.middleware.SessionAuthenticationMiddleware']}): # After password change, user should be anonymous self.user.set_password('new_password') self.user.save() diff --git a/tests/backends/tests.py b/tests/backends/tests.py index 25f7432a46..b7b8c9cade 100644 --- a/tests/backends/tests.py +++ b/tests/backends/tests.py @@ -157,7 +157,11 @@ class PostgreSQLTests(TestCase): self.assert_parses("EnterpriseDB 9.3", 90300) self.assert_parses("PostgreSQL 9.3.6", 90306) self.assert_parses("PostgreSQL 9.4beta1", 90400) - self.assert_parses("PostgreSQL 9.3.1 on i386-apple-darwin9.2.2, compiled by GCC i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5478)", 90301) + self.assert_parses( + "PostgreSQL 9.3.1 on i386-apple-darwin9.2.2, compiled by GCC " + "i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5478)", + 90301 + ) def test_nodb_connection(self): """ @@ -419,13 +423,19 @@ class LongNameTest(TransactionTestCase): models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create() def test_sequence_name_length_limits_m2m(self): - """Test an m2m save of a model with a long name and a long m2m field name doesn't error as on Django >=1.2 this now uses object saves. Ref #8901""" + """ + An m2m save of a model with a long name and a long m2m field name + doesn't error (#8901). + """ obj = models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create() rel_obj = models.Person.objects.create(first_name='Django', last_name='Reinhardt') obj.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.add(rel_obj) def test_sequence_name_length_limits_flush(self): - """Test that sequence resetting as part of a flush with model with long name and long pk name doesn't error. Ref #8901""" + """ + Sequence resetting as part of a flush with model with long name and + long pk name doesn't error (#8901). + """ # A full flush is expensive to the full test, so we dig into the # internals to generate the likely offending SQL and run it manually @@ -834,11 +844,16 @@ class FkConstraintsTests(TransactionTestCase): def test_disable_constraint_checks_manually(self): """ - When constraint checks are disabled, should be able to write bad data without IntegrityErrors. + When constraint checks are disabled, should be able to write bad data + without IntegrityErrors. """ with transaction.atomic(): # Create an Article. - models.Article.objects.create(headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r) + models.Article.objects.create( + headline="Test article", + pub_date=datetime.datetime(2010, 9, 4), + reporter=self.r, + ) # Retrieve it from the DB a = models.Article.objects.get(headline="Test article") a.reporter_id = 30 @@ -852,11 +867,16 @@ class FkConstraintsTests(TransactionTestCase): def test_disable_constraint_checks_context_manager(self): """ - When constraint checks are disabled (using context manager), should be able to write bad data without IntegrityErrors. + When constraint checks are disabled (using context manager), should be + able to write bad data without IntegrityErrors. """ with transaction.atomic(): # Create an Article. - models.Article.objects.create(headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r) + models.Article.objects.create( + headline="Test article", + pub_date=datetime.datetime(2010, 9, 4), + reporter=self.r, + ) # Retrieve it from the DB a = models.Article.objects.get(headline="Test article") a.reporter_id = 30 @@ -873,7 +893,11 @@ class FkConstraintsTests(TransactionTestCase): """ with transaction.atomic(): # Create an Article. - models.Article.objects.create(headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r) + models.Article.objects.create( + headline="Test article", + pub_date=datetime.datetime(2010, 9, 4), + reporter=self.r, + ) # Retrieve it from the DB a = models.Article.objects.get(headline="Test article") a.reporter_id = 30 diff --git a/tests/cache/tests.py b/tests/cache/tests.py index 76becdd948..dca08ee081 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -1844,7 +1844,8 @@ class CacheMiddlewareTest(SimpleTestCase): self.assertEqual(as_view_decorator.cache_timeout, 30) # Timeout value for 'default' cache, i.e. 30 self.assertEqual(as_view_decorator.key_prefix, '') - self.assertEqual(as_view_decorator.cache_alias, 'default') # Value of DEFAULT_CACHE_ALIAS from django.core.cache + # Value of DEFAULT_CACHE_ALIAS from django.core.cache + self.assertEqual(as_view_decorator.cache_alias, 'default') # Next, test with custom values: as_view_decorator_with_custom = CacheMiddleware(cache_timeout=60, cache_alias='other', key_prefix='foo') diff --git a/tests/contenttypes_tests/tests.py b/tests/contenttypes_tests/tests.py index 0d0f9d30b8..dd14eaad55 100644 --- a/tests/contenttypes_tests/tests.py +++ b/tests/contenttypes_tests/tests.py @@ -164,7 +164,10 @@ class GenericForeignKeyTests(IsolatedModelsTestCase): expected = [ checks.Error( "'Model.content_type' is not a ForeignKey.", - hint="GenericForeignKeys must use a ForeignKey to 'contenttypes.ContentType' as the 'content_type' field.", + hint=( + "GenericForeignKeys must use a ForeignKey to " + "'contenttypes.ContentType' as the 'content_type' field." + ), obj=Model.content_object, id='contenttypes.E003', ) @@ -182,7 +185,10 @@ class GenericForeignKeyTests(IsolatedModelsTestCase): expected = [ checks.Error( "'Model.content_type' is not a ForeignKey to 'contenttypes.ContentType'.", - hint="GenericForeignKeys must use a ForeignKey to 'contenttypes.ContentType' as the 'content_type' field.", + hint=( + "GenericForeignKeys must use a ForeignKey to " + "'contenttypes.ContentType' as the 'content_type' field." + ), obj=Model.content_object, id='contenttypes.E004', ) diff --git a/tests/createsuperuser/tests.py b/tests/createsuperuser/tests.py index 08f2ec5322..d5c891c118 100644 --- a/tests/createsuperuser/tests.py +++ b/tests/createsuperuser/tests.py @@ -24,7 +24,10 @@ class MultiDBChangepasswordManagementCommandTestCase(TestCase): command.execute(username="joe", database='other', stdout=out) command_output = out.getvalue().strip() - self.assertEqual(command_output, "Changing password for user 'joe'\nPassword changed successfully for user 'joe'") + self.assertEqual( + command_output, + "Changing password for user 'joe'\nPassword changed successfully for user 'joe'" + ) self.assertTrue(models.User.objects.using('other').get(username="joe").check_password("not qwerty")) diff --git a/tests/custom_columns/tests.py b/tests/custom_columns/tests.py index b258aea710..dccb400daf 100644 --- a/tests/custom_columns/tests.py +++ b/tests/custom_columns/tests.py @@ -95,7 +95,8 @@ class CustomColumnsTests(TestCase): def test_filter_on_nonexistent_field(self): self.assertRaisesMessage( FieldError, - "Cannot resolve keyword 'firstname' into field. Choices are: Author_ID, article, first_name, last_name, primary_set", + "Cannot resolve keyword 'firstname' into field. Choices are: " + "Author_ID, article, first_name, last_name, primary_set", Author.objects.filter, firstname__exact='John' ) diff --git a/tests/db_typecasts/tests.py b/tests/db_typecasts/tests.py index d0e0db20d7..98748abee4 100644 --- a/tests/db_typecasts/tests.py +++ b/tests/db_typecasts/tests.py @@ -53,4 +53,8 @@ class DBTypeCasts(unittest.TestCase): for k, v in six.iteritems(TEST_CASES): for inpt, expected in v: got = getattr(typecasts, k)(inpt) - self.assertEqual(got, expected, "In %s: %r doesn't match %r. Got %r instead." % (k, inpt, expected, got)) + self.assertEqual( + got, + expected, + "In %s: %r doesn't match %r. Got %r instead." % (k, inpt, expected, got) + ) diff --git a/tests/expressions_case/tests.py b/tests/expressions_case/tests.py index 2b269b5893..3f310278c7 100644 --- a/tests/expressions_case/tests.py +++ b/tests/expressions_case/tests.py @@ -689,7 +689,15 @@ class CaseExpressionTests(TestCase): ) self.assertQuerysetEqual( CaseTestModel.objects.all().order_by('pk'), - [(1, Decimal('1.1')), (2, Decimal('2.2')), (3, None), (2, Decimal('2.2')), (3, None), (3, None), (4, None)], + [ + (1, Decimal('1.1')), + (2, Decimal('2.2')), + (3, None), + (2, Decimal('2.2')), + (3, None), + (3, None), + (4, None) + ], transform=attrgetter('integer', 'decimal') ) @@ -934,8 +942,13 @@ class CaseExpressionTests(TestCase): self.assertQuerysetEqual( CaseTestModel.objects.all().order_by('pk'), [ - (1, UUID('11111111111111111111111111111111')), (2, UUID('22222222222222222222222222222222')), (3, None), - (2, UUID('22222222222222222222222222222222')), (3, None), (3, None), (4, None) + (1, UUID('11111111111111111111111111111111')), + (2, UUID('22222222222222222222222222222222')), + (3, None), + (2, UUID('22222222222222222222222222222222')), + (3, None), + (3, None), + (4, None), ], transform=attrgetter('integer', 'uuid') ) diff --git a/tests/extra_regress/tests.py b/tests/extra_regress/tests.py index aba6e326e1..242487a060 100644 --- a/tests/extra_regress/tests.py +++ b/tests/extra_regress/tests.py @@ -185,100 +185,174 @@ class ExtraRegressTests(TestCase): obj.save() self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values()), - [{'bar': 'second', 'third': 'third', 'second': 'second', 'whiz': 'third', 'foo': 'first', 'id': obj.pk, 'first': 'first'}] + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values() + ), + [{ + 'bar': 'second', 'third': 'third', 'second': 'second', 'whiz': 'third', 'foo': 'first', + 'id': obj.pk, 'first': 'first' + }] ) # Extra clauses after an empty values clause are still included self.assertEqual( - list(TestObject.objects.values().extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third'))))), - [{'bar': 'second', 'third': 'third', 'second': 'second', 'whiz': 'third', 'foo': 'first', 'id': obj.pk, 'first': 'first'}] + list( + TestObject.objects + .values() + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + ), + [{ + 'bar': 'second', 'third': 'third', 'second': 'second', 'whiz': 'third', 'foo': 'first', + 'id': obj.pk, 'first': 'first' + }] ) # Extra columns are ignored if not mentioned in the values() clause self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values('first', 'second')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values('first', 'second') + ), [{'second': 'second', 'first': 'first'}] ) # Extra columns after a non-empty values() clause are ignored self.assertEqual( - list(TestObject.objects.values('first', 'second').extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third'))))), + list( + TestObject.objects + .values('first', 'second') + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + ), [{'second': 'second', 'first': 'first'}] ) # Extra columns can be partially returned self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values('first', 'second', 'foo')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values('first', 'second', 'foo') + ), [{'second': 'second', 'foo': 'first', 'first': 'first'}] ) # Also works if only extra columns are included self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values('foo', 'whiz')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values('foo', 'whiz') + ), [{'foo': 'first', 'whiz': 'third'}] ) # Values list works the same way # All columns are returned for an empty values_list() self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list()), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list() + ), [('first', 'second', 'third', obj.pk, 'first', 'second', 'third')] ) # Extra columns after an empty values_list() are still included self.assertEqual( - list(TestObject.objects.values_list().extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third'))))), + list( + TestObject.objects + .values_list() + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + ), [('first', 'second', 'third', obj.pk, 'first', 'second', 'third')] ) # Extra columns ignored completely if not mentioned in values_list() self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('first', 'second')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('first', 'second') + ), [('first', 'second')] ) # Extra columns after a non-empty values_list() clause are ignored completely self.assertEqual( - list(TestObject.objects.values_list('first', 'second').extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third'))))), + list( + TestObject.objects + .values_list('first', 'second') + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + ), [('first', 'second')] ) self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('second', flat=True)), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('second', flat=True) + ), ['second'] ) # Only the extra columns specified in the values_list() are returned self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('first', 'second', 'whiz')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('first', 'second', 'whiz') + ), [('first', 'second', 'third')] ) # ...also works if only extra columns are included self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('foo', 'whiz')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('foo', 'whiz') + ), [('first', 'third')] ) self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('whiz', flat=True)), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('whiz', flat=True) + ), ['third'] ) # ... and values are returned in the order they are specified self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('whiz', 'foo')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('whiz', 'foo') + ), [('third', 'first')] ) self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('first', 'id')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('first', 'id') + ), [('first', obj.pk)] ) self.assertEqual( - list(TestObject.objects.extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))).values_list('whiz', 'first', 'bar', 'id')), + list( + TestObject.objects + .extra(select=OrderedDict((('foo', 'first'), ('bar', 'second'), ('whiz', 'third')))) + .values_list('whiz', 'first', 'bar', 'id') + ), [('third', 'first', 'second', obj.pk)] ) diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py index 2fe1499738..1d0d0ffee1 100644 --- a/tests/file_uploads/tests.py +++ b/tests/file_uploads/tests.py @@ -156,14 +156,18 @@ class FileUploadTests(TestCase): (#22971). """ payload = client.FakePayload() - payload.write('\r\n'.join([ - '--' + client.BOUNDARY, - 'Content-Disposition: form-data; name*=UTF-8\'\'file_unicode; filename*=UTF-8\'\'%s' % urlquote(UNICODE_FILENAME), - 'Content-Type: application/octet-stream', - '', - 'You got pwnd.\r\n', - '\r\n--' + client.BOUNDARY + '--\r\n' - ])) + payload.write( + '\r\n'.join([ + '--' + client.BOUNDARY, + 'Content-Disposition: form-data; name*=UTF-8\'\'file_unicode; filename*=UTF-8\'\'%s' % urlquote( + UNICODE_FILENAME + ), + 'Content-Type: application/octet-stream', + '', + 'You got pwnd.\r\n', + '\r\n--' + client.BOUNDARY + '--\r\n' + ]) + ) r = { 'CONTENT_LENGTH': len(payload), diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py index a89b33aa65..f48a689f6f 100644 --- a/tests/fixtures/tests.py +++ b/tests/fixtures/tests.py @@ -89,32 +89,83 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): ]) # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place ' + 'on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) # Try just dumping the contents of fixtures.Category - self._dumpdata_assert(['fixtures.Category'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}]') + self._dumpdata_assert( + ['fixtures.Category'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", ' + '"title": "News Stories"}}]' + ) # ...and just fixtures.Article - self._dumpdata_assert(['fixtures.Article'], '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures.Article'], + '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", ' + '"pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": ' + '"Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) # ...and both - self._dumpdata_assert(['fixtures.Category', 'fixtures.Article'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures.Category', 'fixtures.Article'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", ' + '"title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has ' + 'no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", ' + '"fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) # Specify a specific model twice - self._dumpdata_assert(['fixtures.Article', 'fixtures.Article'], '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures.Article', 'fixtures.Article'], + ( + '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", ' + '"pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": ' + '"Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) + ) # Specify a dump that specifies Article both explicitly and implicitly - self._dumpdata_assert(['fixtures.Article', 'fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures.Article', 'fixtures'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place ' + 'on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) # Specify a dump that specifies Article both explicitly and implicitly, # but lists the app first (#22025). - self._dumpdata_assert(['fixtures', 'fixtures.Article'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures', 'fixtures.Article'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place ' + 'on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) # Same again, but specify in the reverse order - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no ' + 'place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields":' + ' {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) # Specify one model from one application, and an entire other application. - self._dumpdata_assert(['fixtures.Category', 'sites'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}]') + self._dumpdata_assert( + ['fixtures.Category', 'sites'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": ' + '"example.com"}}]' + ) # Load fixture 2. JSON file imported by default. Overwrites some existing objects management.call_command('loaddata', 'fixture2.json', verbosity=0) @@ -174,20 +225,106 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): ]) # By default, you get raw keys on dumpdata - self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [3, 1]}}]') + self._dumpdata_assert( + ['fixtures.book'], + '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [3, 1]}}]' + ) # But you can get natural keys if you ask for them and they are available - self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_foreign_keys=True) + self._dumpdata_assert( + ['fixtures.book'], + '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist ' + 'formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', + natural_foreign_keys=True + ) # You can also omit the primary keys for models that we can get later with natural keys. - self._dumpdata_assert(['fixtures.person'], '[{"fields": {"name": "Django Reinhardt"}, "model": "fixtures.person"}, {"fields": {"name": "Stephane Grappelli"}, "model": "fixtures.person"}, {"fields": {"name": "Artist formerly known as \\"Prince\\""}, "model": "fixtures.person"}]', natural_primary_keys=True) + self._dumpdata_assert( + ['fixtures.person'], + '[{"fields": {"name": "Django Reinhardt"}, "model": "fixtures.person"}, {"fields": {"name": "Stephane ' + 'Grappelli"}, "model": "fixtures.person"}, {"fields": {"name": "Artist formerly known as ' + '\\"Prince\\""}, "model": "fixtures.person"}]', + natural_primary_keys=True + ) # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is great!", "pub_date": "2006-06-16T11:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}, {"pk": 4, "model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": "2006-06-16T15:00:00"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML identified as leading cause of cancer", "pub_date": "2006-06-16T16:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "world domination", "tagged_id": 4}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Artist formerly known as \\"Prince\\""}}, {"pk": 1, "model": "fixtures.visa", "fields": {"person": ["Django Reinhardt"], "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 2, "model": "fixtures.visa", "fields": {"person": ["Stephane Grappelli"], "permissions": [["add_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"person": ["Artist formerly known as \\"Prince\\""], "permissions": [["change_user", "auth", "user"]]}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_foreign_keys=True) + self._dumpdata_assert( + ['fixtures'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is ' + 'great!", "pub_date": "2006-06-16T11:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}, {"pk": 4, ' + '"model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": ' + '"2006-06-16T15:00:00"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML ' + 'identified as leading cause of cancer", "pub_date": "2006-06-16T16:00:00"}}, {"pk": 1, "model": ' + '"fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": ' + '3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": ' + '"legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", ' + '"article"], "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": ' + '{"tagged_type": ["fixtures", "article"], "name": "world domination", "tagged_id": 4}}, {"pk": 1, ' + '"model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": ' + '"fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 3, "model": "fixtures.person", ' + '"fields": {"name": "Artist formerly known as \\"Prince\\""}}, {"pk": 1, "model": "fixtures.visa", ' + '"fields": {"person": ["Django Reinhardt"], "permissions": [["add_user", "auth", "user"], ' + '["change_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 2, "model": ' + '"fixtures.visa", "fields": {"person": ["Stephane Grappelli"], "permissions": [["add_user", "auth", ' + '"user"], ["delete_user", "auth", "user"]]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"person":' + ' ["Artist formerly known as \\"Prince\\""], "permissions": [["change_user", "auth", "user"]]}}, ' + '{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist ' + 'formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', + natural_foreign_keys=True + ) # Dump the current contents of the database as an XML fixture - self._dumpdata_assert(['fixtures'], """ -News StoriesLatest news storiesPoker on TV is great!2006-06-16T11:00:00Copyright is fine the way it is2006-06-16T14:00:00Django conquers world!2006-06-16T15:00:00XML identified as leading cause of cancer2006-06-16T16:00:00copyrightfixturesarticle3legalfixturesarticle3djangofixturesarticle4world dominationfixturesarticle4Django ReinhardtStephane GrappelliArtist formerly known as "Prince"Django Reinhardtadd_userauthuserchange_userauthuserdelete_userauthuserStephane Grappelliadd_userauthuserdelete_userauthuserArtist formerly known as "Prince"change_userauthuserMusic for all agesArtist formerly known as "Prince"Django Reinhardt""", format='xml', natural_foreign_keys=True) + self._dumpdata_assert( + ['fixtures'], + 'News StoriesLatest news storiesPoker on TV is great!2006-06-16T11:00:00Copyright is fine the way it ' + 'is2006-06-16T14:00:00Django conquers world!' + '2006-06-16T15:00:00XML identified as leading ' + 'cause of cancer2006-06-16T16:00:00' + 'copyright' + 'fixtures' + 'article3' + 'legal' + '' + 'fixturesarticle3djangofixturesarticle4' + 'world dominationfixturesarticle' + '4Django Reinhardt' + 'Stephane Grappelli' + '' + 'Artist formerly known as "Prince"Django Reinhardt' + 'add_user' + 'authuserchange_user' + 'authuserdelete_user' + 'authuserStephane' + ' Grappelli' + 'add_userauthuser' + 'delete_userauthuser' + 'Artist formerly known as "Prince"change_user' + 'authuserMusic for all agesArtist formerly known as ' + '"Prince"Django Reinhardt' + '', + format='xml', natural_foreign_keys=True + ) def test_dumpdata_with_excludes(self): # Load fixture1 which has a site, two articles, and a category @@ -203,20 +340,28 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): # Excluding fixtures.Article/Book should leave fixtures.Category self._dumpdata_assert( ['sites', 'fixtures'], - '[{"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, {"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}]', - exclude_list=['fixtures.Article', 'fixtures.Book']) + '[{"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, ' + '{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}]', + exclude_list=['fixtures.Article', 'fixtures.Book'] + ) # Excluding fixtures and fixtures.Article/Book should be a no-op self._dumpdata_assert( ['sites', 'fixtures'], - '[{"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, {"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}]', - exclude_list=['fixtures.Article', 'fixtures.Book']) + '[{"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, ' + '{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}]', + exclude_list=['fixtures.Article', 'fixtures.Book'] + ) # Excluding sites and fixtures.Article/Book should only leave fixtures.Category self._dumpdata_assert( ['sites', 'fixtures'], - '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}]', - exclude_list=['fixtures.Article', 'fixtures.Book', 'sites']) + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}]', + exclude_list=['fixtures.Article', 'fixtures.Book', 'sites'] + ) # Excluding a bogus app should throw an error with six.assertRaisesRegex(self, management.CommandError, @@ -239,23 +384,34 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): self.assertQuerysetEqual(Spy.objects.all(), ['']) # Use the default manager - self._dumpdata_assert(['fixtures.Spy'], '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % spy1.pk) + self._dumpdata_assert( + ['fixtures.Spy'], + '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % spy1.pk + ) # Dump using Django's base manager. Should return all objects, # even those normally filtered by the manager - self._dumpdata_assert(['fixtures.Spy'], '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": true}}, {"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % (spy2.pk, spy1.pk), use_base_manager=True) + self._dumpdata_assert( + ['fixtures.Spy'], + '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": true}}, {"pk": %d, "model": ' + '"fixtures.spy", "fields": {"cover_blown": false}}]' % (spy2.pk, spy1.pk), + use_base_manager=True + ) def test_dumpdata_with_pks(self): management.call_command('loaddata', 'fixture1.json', verbosity=0) management.call_command('loaddata', 'fixture2.json', verbosity=0) self._dumpdata_assert( ['fixtures.Article'], - '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', + '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", ' + '"pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": ' + '"Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', primary_keys='2,3' ) self._dumpdata_assert( ['fixtures.Article'], - '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}]', + '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", ' + '"pub_date": "2006-06-16T12:00:00"}}]', primary_keys='2' ) @@ -263,7 +419,9 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): "You can only use --pks option with one model"): self._dumpdata_assert( ['fixtures'], - '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', + '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", ' + '"pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', primary_keys='2,3' ) @@ -271,7 +429,9 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): "You can only use --pks option with one model"): self._dumpdata_assert( '', - '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', + '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", ' + '"pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', primary_keys='2,3' ) @@ -279,14 +439,22 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): "You can only use --pks option with one model"): self._dumpdata_assert( ['fixtures.Article', 'fixtures.category'], - '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', + '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", ' + '"pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]', primary_keys='2,3' ) def test_dumpdata_with_file_output(self): management.call_command('loaddata', 'fixture1.json', verbosity=0) - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]', - filename='dumpdata.json') + self._dumpdata_assert( + ['fixtures'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place ' + 'on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]', + filename='dumpdata.json' + ) def test_dumpdata_progressbar(self): """ @@ -414,11 +582,42 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): ], ordered=False) # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}]', natural_foreign_keys=True) + self._dumpdata_assert( + ['fixtures'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place ' + 'on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 1, "model": ' + '"fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": ' + '3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": ' + '"law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django ' + 'Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, ' + '{"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}]', + natural_foreign_keys=True + ) # Dump the current contents of the database as an XML fixture - self._dumpdata_assert(['fixtures'], """ -News StoriesLatest news storiesPoker has no place on ESPN2006-06-16T12:00:00Time to reform copyright2006-06-16T13:00:00copyrightfixturesarticle3lawfixturesarticle3Django ReinhardtStephane GrappelliPrince""", format='xml', natural_foreign_keys=True) + self._dumpdata_assert( + ['fixtures'], + 'News StoriesLatest news storiesPoker has no place on ESPN' + '2006-06-16T12:00:00Time to reform copyright' + '2006-06-16T13:00:00copyrightfixtures' + 'article3' + 'lawfixtures' + 'article3' + 'Django Reinhardt' + 'Stephane ' + 'Grappelli' + 'Prince', + format='xml', natural_foreign_keys=True + ) class NonExistentFixtureTests(TestCase): @@ -476,7 +675,13 @@ class FixtureTransactionTests(DumpDataAssertMixin, TransactionTestCase): ]) # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]') + self._dumpdata_assert( + ['fixtures'], + '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": ' + '"News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place ' + 'on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": ' + '{"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]' + ) # Load fixture 4 (compressed), using format discovery management.call_command('loaddata', 'fixture4', verbosity=0) diff --git a/tests/fixtures_regress/tests.py b/tests/fixtures_regress/tests.py index e533be3bb6..02a841f5ef 100644 --- a/tests/fixtures_regress/tests.py +++ b/tests/fixtures_regress/tests.py @@ -239,7 +239,10 @@ class TestFixtures(TestCase): ) warning = warning_list.pop() self.assertEqual(warning.category, RuntimeWarning) - self.assertEqual(str(warning.message), "No fixture data found for 'bad_fixture2'. (File format may be invalid.)") + self.assertEqual( + str(warning.message), + "No fixture data found for 'bad_fixture2'. (File format may be invalid.)" + ) def test_invalid_data_no_ext(self): """ @@ -256,7 +259,10 @@ class TestFixtures(TestCase): ) warning = warning_list.pop() self.assertEqual(warning.category, RuntimeWarning) - self.assertEqual(str(warning.message), "No fixture data found for 'bad_fixture2'. (File format may be invalid.)") + self.assertEqual( + str(warning.message), + "No fixture data found for 'bad_fixture2'. (File format may be invalid.)" + ) def test_empty(self): """ @@ -272,7 +278,8 @@ class TestFixtures(TestCase): ) warning = warning_list.pop() self.assertEqual(warning.category, RuntimeWarning) - self.assertEqual(str(warning.message), "No fixture data found for 'empty'. (File format may be invalid.)") + self.assertEqual(str(warning.message), + "No fixture data found for 'empty'. (File format may be invalid.)") def test_error_message(self): """ @@ -289,7 +296,10 @@ class TestFixtures(TestCase): ) warning = warning_list.pop() self.assertEqual(warning.category, RuntimeWarning) - self.assertEqual(str(warning.message), "No fixture data found for 'bad_fixture2'. (File format may be invalid.)") + self.assertEqual( + str(warning.message), + "No fixture data found for 'bad_fixture2'. (File format may be invalid.)" + ) def test_pg_sequence_resetting_checks(self): """ @@ -394,9 +404,18 @@ class TestFixtures(TestCase): data = re.sub('0{6,}[0-9]', '', data) animals_data = sorted([ - {"pk": 1, "model": "fixtures_regress.animal", "fields": {"count": 3, "weight": 1.2, "name": "Lion", "latin_name": "Panthera leo"}}, - {"pk": 10, "model": "fixtures_regress.animal", "fields": {"count": 42, "weight": 1.2, "name": "Emu", "latin_name": "Dromaius novaehollandiae"}}, - {"pk": animal.pk, "model": "fixtures_regress.animal", "fields": {"count": 2, "weight": 2.2, "name": "Platypus", "latin_name": "Ornithorhynchus anatinus"}}, + { + "pk": 1, "model": "fixtures_regress.animal", + "fields": {"count": 3, "weight": 1.2, "name": "Lion", "latin_name": "Panthera leo"} + }, + { + "pk": 10, "model": "fixtures_regress.animal", + "fields": {"count": 42, "weight": 1.2, "name": "Emu", "latin_name": "Dromaius novaehollandiae"} + }, + { + "pk": animal.pk, "model": "fixtures_regress.animal", + "fields": {"count": 2, "weight": 2.2, "name": "Platypus", "latin_name": "Ornithorhynchus anatinus"} + }, ], key=lambda x: x["pk"]) data = sorted(json.loads(data), key=lambda x: x["pk"]) @@ -636,7 +655,13 @@ class NaturalKeyFixtureTests(TestCase): ) self.assertJSONEqual( out.getvalue(), - """[{"fields": {"main": null, "name": "Amazon"}, "model": "fixtures_regress.store"}, {"fields": {"main": null, "name": "Borders"}, "model": "fixtures_regress.store"}, {"fields": {"name": "Neal Stephenson"}, "model": "fixtures_regress.person"}, {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}]""" + """ + [{"fields": {"main": null, "name": "Amazon"}, "model": "fixtures_regress.store"}, + {"fields": {"main": null, "name": "Borders"}, "model": "fixtures_regress.store"}, + {"fields": {"name": "Neal Stephenson"}, "model": "fixtures_regress.person"}, + {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], + "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}] + """ ) def test_dependency_sorting(self): @@ -711,7 +736,8 @@ class NaturalKeyFixtureTests(TestCase): def test_dependency_sorting_tight_circular(self): self.assertRaisesMessage( RuntimeError, - """Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list.""", + "Can't resolve dependencies for fixtures_regress.Circle1, " + "fixtures_regress.Circle2 in serialized app list.", serializers.sort_dependencies, [('fixtures_regress', [Person, Circle2, Circle1, Store, Book])], ) @@ -719,7 +745,8 @@ class NaturalKeyFixtureTests(TestCase): def test_dependency_sorting_tight_circular_2(self): self.assertRaisesMessage( RuntimeError, - """Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list.""", + "Can't resolve dependencies for fixtures_regress.Circle1, " + "fixtures_regress.Circle2 in serialized app list.", serializers.sort_dependencies, [('fixtures_regress', [Circle1, Book, Circle2])], ) @@ -727,7 +754,8 @@ class NaturalKeyFixtureTests(TestCase): def test_dependency_self_referential(self): self.assertRaisesMessage( RuntimeError, - """Can't resolve dependencies for fixtures_regress.Circle3 in serialized app list.""", + "Can't resolve dependencies for fixtures_regress.Circle3 in " + "serialized app list.", serializers.sort_dependencies, [('fixtures_regress', [Book, Circle3])], ) @@ -735,7 +763,9 @@ class NaturalKeyFixtureTests(TestCase): def test_dependency_sorting_long(self): self.assertRaisesMessage( RuntimeError, - """Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2, fixtures_regress.Circle3 in serialized app list.""", + "Can't resolve dependencies for fixtures_regress.Circle1, " + "fixtures_regress.Circle2, fixtures_regress.Circle3 in serialized " + "app list.", serializers.sort_dependencies, [('fixtures_regress', [Person, Circle2, Circle1, Circle3, Store, Book])], ) @@ -772,7 +802,9 @@ class NaturalKeyFixtureTests(TestCase): books = Book.objects.all() self.assertEqual( books.__repr__(), - """[, , ]""" + "[, " + ", " + "]" ) diff --git a/tests/forms_tests/tests/test_error_messages.py b/tests/forms_tests/tests/test_error_messages.py index d2a80051ce..0632107e1e 100644 --- a/tests/forms_tests/tests/test_error_messages.py +++ b/tests/forms_tests/tests/test_error_messages.py @@ -157,7 +157,11 @@ class FormsErrorMessagesTestCase(SimpleTestCase, AssertFormErrorsMixin): f = URLField(error_messages=e, max_length=17) self.assertFormErrors(['REQUIRED'], f.clean, '') self.assertFormErrors(['INVALID'], f.clean, 'abc.c') - self.assertFormErrors(['"http://djangoproject.com" has more than 17 characters.'], f.clean, 'djangoproject.com') + self.assertFormErrors( + ['"http://djangoproject.com" has more than 17 characters.'], + f.clean, + 'djangoproject.com' + ) def test_booleanfield(self): e = { @@ -226,8 +230,14 @@ class FormsErrorMessagesTestCase(SimpleTestCase, AssertFormErrorsMixin): # This form should print errors the default way. form1 = TestForm({'first_name': 'John'}) - self.assertHTMLEqual(str(form1['last_name'].errors), '
        • This field is required.
        ') - self.assertHTMLEqual(str(form1.errors['__all__']), '
        • I like to be awkward.
        ') + self.assertHTMLEqual( + str(form1['last_name'].errors), + '
        • This field is required.
        ' + ) + self.assertHTMLEqual( + str(form1.errors['__all__']), + '
        • I like to be awkward.
        ' + ) # This one should wrap error groups in the customized way. form2 = TestForm({'first_name': 'John'}, error_class=CustomErrorList) diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py index 6234f5c455..5e4b4269db 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -117,14 +117,18 @@ class FieldsTests(SimpleTestCase): f = CharField(max_length=10, required=False) self.assertEqual('12345', f.clean('12345')) self.assertEqual('1234567890', f.clean('1234567890')) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 10 characters (it has 11).'", f.clean, '1234567890a') + msg = "'Ensure this value has at most 10 characters (it has 11).'" + with self.assertRaisesMessage(ValidationError, msg): + f.clean('1234567890a') self.assertEqual(f.max_length, 10) self.assertEqual(f.min_length, None) def test_charfield_4(self): f = CharField(min_length=10, required=False) self.assertEqual('', f.clean('')) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 10 characters (it has 5).'", f.clean, '12345') + msg = "'Ensure this value has at least 10 characters (it has 5).'" + with self.assertRaisesMessage(ValidationError, msg): + f.clean('12345') self.assertEqual('1234567890', f.clean('1234567890')) self.assertEqual('1234567890a', f.clean('1234567890a')) self.assertEqual(f.max_length, None) @@ -133,7 +137,9 @@ class FieldsTests(SimpleTestCase): def test_charfield_5(self): f = CharField(min_length=10, required=True) self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, '') - self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 10 characters (it has 5).'", f.clean, '12345') + msg = "'Ensure this value has at least 10 characters (it has 5).'" + with self.assertRaisesMessage(ValidationError, msg): + f.clean('12345') self.assertEqual('1234567890', f.clean('1234567890')) self.assertEqual('1234567890a', f.clean('1234567890a')) self.assertEqual(f.max_length, None) @@ -327,7 +333,10 @@ class FieldsTests(SimpleTestCase): f = FloatField(max_value=1.5, min_value=0.5) self.assertWidgetRendersTo(f, '') self.assertRaisesMessage(ValidationError, "'Ensure this value is less than or equal to 1.5.'", f.clean, '1.6') - self.assertRaisesMessage(ValidationError, "'Ensure this value is greater than or equal to 0.5.'", f.clean, '0.4') + self.assertRaisesMessage( + ValidationError, "'Ensure this value is greater than or equal to 0.5.'", + f.clean, '0.4' + ) self.assertEqual(1.5, f.clean('1.5')) self.assertEqual(0.5, f.clean('0.5')) self.assertEqual(f.max_value, 1.5) @@ -377,16 +386,34 @@ class FieldsTests(SimpleTestCase): self.assertEqual(f.clean(' 1.0'), Decimal("1.0")) self.assertEqual(f.clean(' 1.0 '), Decimal("1.0")) self.assertRaisesMessage(ValidationError, "'Enter a number.'", f.clean, '1.0a') - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 4 digits in total.'", f.clean, '123.45') - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 2 decimal places.'", f.clean, '1.234') - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 2 digits before the decimal point.'", f.clean, '123.4') + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 4 digits in total.'", + f.clean, '123.45' + ) + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 2 decimal places.'", + f.clean, '1.234' + ) + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 2 digits before the decimal point.'", + f.clean, '123.4' + ) self.assertEqual(f.clean('-12.34'), Decimal("-12.34")) - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 4 digits in total.'", f.clean, '-123.45') + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 4 digits in total.'", + f.clean, '-123.45' + ) self.assertEqual(f.clean('-.12'), Decimal("-0.12")) self.assertEqual(f.clean('-00.12'), Decimal("-0.12")) self.assertEqual(f.clean('-000.12'), Decimal("-0.12")) - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 2 decimal places.'", f.clean, '-000.123') - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 4 digits in total.'", f.clean, '-000.12345') + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 2 decimal places.'", + f.clean, '-000.123' + ) + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 4 digits in total.'", + f.clean, '-000.12345' + ) self.assertRaisesMessage(ValidationError, "'Enter a number.'", f.clean, '--0.12') self.assertEqual(f.max_digits, 4) self.assertEqual(f.decimal_places, 2) @@ -407,7 +434,10 @@ class FieldsTests(SimpleTestCase): f = DecimalField(max_digits=4, decimal_places=2, max_value=Decimal('1.5'), min_value=Decimal('0.5')) self.assertWidgetRendersTo(f, '') self.assertRaisesMessage(ValidationError, "'Ensure this value is less than or equal to 1.5.'", f.clean, '1.6') - self.assertRaisesMessage(ValidationError, "'Ensure this value is greater than or equal to 0.5.'", f.clean, '0.4') + self.assertRaisesMessage( + ValidationError, "'Ensure this value is greater than or equal to 0.5.'", + f.clean, '0.4' + ) self.assertEqual(f.clean('1.5'), Decimal("1.5")) self.assertEqual(f.clean('0.5'), Decimal("0.5")) self.assertEqual(f.clean('.5'), Decimal("0.5")) @@ -419,7 +449,10 @@ class FieldsTests(SimpleTestCase): def test_decimalfield_4(self): f = DecimalField(decimal_places=2) - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 2 decimal places.'", f.clean, '0.00000001') + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 2 decimal places.'", + f.clean, '0.00000001' + ) def test_decimalfield_5(self): f = DecimalField(max_digits=3) @@ -429,13 +462,19 @@ class FieldsTests(SimpleTestCase): self.assertEqual(f.clean('0000000.100'), Decimal("0.100")) # Only leading whole zeros "collapse" to one digit. self.assertEqual(f.clean('000000.02'), Decimal('0.02')) - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 3 digits in total.'", f.clean, '000000.0002') + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 3 digits in total.'", + f.clean, '000000.0002' + ) self.assertEqual(f.clean('.002'), Decimal("0.002")) def test_decimalfield_6(self): f = DecimalField(max_digits=2, decimal_places=2) self.assertEqual(f.clean('.01'), Decimal(".01")) - self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 0 digits before the decimal point.'", f.clean, '1.1') + self.assertRaisesMessage( + ValidationError, "'Ensure that there are no more than 0 digits before the decimal point.'", + f.clean, '1.1' + ) def test_decimalfield_scientific(self): f = DecimalField(max_digits=2, decimal_places=2) @@ -588,8 +627,14 @@ class FieldsTests(SimpleTestCase): f = DateTimeField() self.assertEqual(datetime.datetime(2006, 10, 25, 0, 0), f.clean(datetime.date(2006, 10, 25))) self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30), f.clean(datetime.datetime(2006, 10, 25, 14, 30))) - self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 59), f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))) - self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 59, 200), f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))) + self.assertEqual( + datetime.datetime(2006, 10, 25, 14, 30, 59), + f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) + ) + self.assertEqual( + datetime.datetime(2006, 10, 25, 14, 30, 59, 200), + f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) + ) self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 45, 200), f.clean('2006-10-25 14:30:45.000200')) self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 45, 200), f.clean('2006-10-25 14:30:45.0002')) self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 45), f.clean('2006-10-25 14:30:45')) @@ -613,8 +658,14 @@ class FieldsTests(SimpleTestCase): f = DateTimeField(input_formats=['%Y %m %d %I:%M %p']) self.assertEqual(datetime.datetime(2006, 10, 25, 0, 0), f.clean(datetime.date(2006, 10, 25))) self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30), f.clean(datetime.datetime(2006, 10, 25, 14, 30))) - self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 59), f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))) - self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 59, 200), f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))) + self.assertEqual( + datetime.datetime(2006, 10, 25, 14, 30, 59), + f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) + ) + self.assertEqual( + datetime.datetime(2006, 10, 25, 14, 30, 59, 200), + f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) + ) self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30), f.clean('2006 10 25 2:30 PM')) self.assertRaisesMessage(ValidationError, "'Enter a valid date/time.'", f.clean, '2006-10-25 14:30:45') @@ -717,11 +768,22 @@ class FieldsTests(SimpleTestCase): def test_regexfield_5(self): f = RegexField('^[0-9]+$', min_length=5, max_length=10) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 5 characters (it has 3).'", f.clean, '123') - six.assertRaisesRegex(self, ValidationError, "'Ensure this value has at least 5 characters \(it has 3\)\.', u?'Enter a valid value\.'", f.clean, 'abc') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at least 5 characters (it has 3).'", + f.clean, '123' + ) + six.assertRaisesRegex( + self, ValidationError, + "'Ensure this value has at least 5 characters \(it has 3\)\.'," + " u?'Enter a valid value\.'", + f.clean, 'abc' + ) self.assertEqual('12345', f.clean('12345')) self.assertEqual('1234567890', f.clean('1234567890')) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 10 characters (it has 11).'", f.clean, '12345678901') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at most 10 characters (it has 11).'", + f.clean, '12345678901' + ) self.assertRaisesMessage(ValidationError, "'Enter a valid value.'", f.clean, '12345a') def test_regexfield_6(self): @@ -769,9 +831,15 @@ class FieldsTests(SimpleTestCase): def test_emailfield_min_max_length(self): f = EmailField(min_length=10, max_length=15) self.assertWidgetRendersTo(f, '') - self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 10 characters (it has 9).'", f.clean, 'a@foo.com') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at least 10 characters (it has 9).'", + f.clean, 'a@foo.com' + ) self.assertEqual('alf@foo.com', f.clean('alf@foo.com')) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 15 characters (it has 20).'", f.clean, 'alf123456788@foo.com') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at most 15 characters (it has 20).'", + f.clean, 'alf123456788@foo.com' + ) # FileField ################################################################## @@ -783,19 +851,43 @@ class FieldsTests(SimpleTestCase): self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None) self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None, '') self.assertEqual('files/test2.pdf', f.clean(None, 'files/test2.pdf')) - self.assertRaisesMessage(ValidationError, "'No file was submitted. Check the encoding type on the form.'", f.clean, SimpleUploadedFile('', b'')) - self.assertRaisesMessage(ValidationError, "'No file was submitted. Check the encoding type on the form.'", f.clean, SimpleUploadedFile('', b''), '') + self.assertRaisesMessage( + ValidationError, "'No file was submitted. Check the encoding type on the form.'", + f.clean, SimpleUploadedFile('', b'') + ) + self.assertRaisesMessage( + ValidationError, "'No file was submitted. Check the encoding type on the form.'", + f.clean, SimpleUploadedFile('', b''), '' + ) self.assertEqual('files/test3.pdf', f.clean(None, 'files/test3.pdf')) - self.assertRaisesMessage(ValidationError, "'No file was submitted. Check the encoding type on the form.'", f.clean, 'some content that is not a file') - self.assertRaisesMessage(ValidationError, "'The submitted file is empty.'", f.clean, SimpleUploadedFile('name', None)) - self.assertRaisesMessage(ValidationError, "'The submitted file is empty.'", f.clean, SimpleUploadedFile('name', b'')) + self.assertRaisesMessage( + ValidationError, "'No file was submitted. Check the encoding type on the form.'", + f.clean, 'some content that is not a file' + ) + self.assertRaisesMessage( + ValidationError, "'The submitted file is empty.'", + f.clean, SimpleUploadedFile('name', None) + ) + self.assertRaisesMessage( + ValidationError, "'The submitted file is empty.'", + f.clean, SimpleUploadedFile('name', b'') + ) self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', b'Some File Content')))) - self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8'))))) - self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', b'Some File Content'), 'files/test4.pdf'))) + self.assertIsInstance( + f.clean(SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8'))), + SimpleUploadedFile + ) + self.assertIsInstance( + f.clean(SimpleUploadedFile('name', b'Some File Content'), 'files/test4.pdf'), + SimpleUploadedFile + ) def test_filefield_2(self): f = FileField(max_length=5) - self.assertRaisesMessage(ValidationError, "'Ensure this filename has at most 5 characters (it has 18).'", f.clean, SimpleUploadedFile('test_maxlength.txt', b'hello world')) + self.assertRaisesMessage( + ValidationError, "'Ensure this filename has at most 5 characters (it has 18).'", + f.clean, SimpleUploadedFile('test_maxlength.txt', b'hello world') + ) self.assertEqual('files/test1.pdf', f.clean('', 'files/test1.pdf')) self.assertEqual('files/test2.pdf', f.clean(None, 'files/test2.pdf')) self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', b'Some File Content')))) @@ -897,8 +989,14 @@ class FieldsTests(SimpleTestCase): self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://inv-.alid-.com') self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://inv-.-alid.com') self.assertEqual('http://valid-----hyphens.com', f.clean('http://valid-----hyphens.com')) - self.assertEqual('http://some.idn.xyz\xe4\xf6\xfc\xdfabc.domain.com:123/blah', f.clean('http://some.idn.xyzäöüßabc.domain.com:123/blah')) - self.assertEqual('http://www.example.com/s/http://code.djangoproject.com/ticket/13804', f.clean('www.example.com/s/http://code.djangoproject.com/ticket/13804')) + self.assertEqual( + 'http://some.idn.xyz\xe4\xf6\xfc\xdfabc.domain.com:123/blah', + f.clean('http://some.idn.xyzäöüßabc.domain.com:123/blah') + ) + self.assertEqual( + 'http://www.example.com/s/http://code.djangoproject.com/ticket/13804', + f.clean('www.example.com/s/http://code.djangoproject.com/ticket/13804') + ) self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, '[a') self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://[a') @@ -926,9 +1024,15 @@ class FieldsTests(SimpleTestCase): def test_urlfield_5(self): f = URLField(min_length=15, max_length=20) self.assertWidgetRendersTo(f, '') - self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 15 characters (it has 12).'", f.clean, 'http://f.com') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at least 15 characters (it has 12).'", + f.clean, 'http://f.com' + ) self.assertEqual('http://example.com', f.clean('http://example.com')) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 37).'", f.clean, 'http://abcdefghijklmnopqrstuvwxyz.com') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at most 20 characters (it has 37).'", + f.clean, 'http://abcdefghijklmnopqrstuvwxyz.com' + ) def test_urlfield_6(self): f = URLField(required=False) @@ -1033,7 +1137,10 @@ class FieldsTests(SimpleTestCase): self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None) self.assertEqual('1', f.clean(1)) self.assertEqual('1', f.clean('1')) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", f.clean, '3') + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", + f.clean, '3' + ) def test_choicefield_2(self): f = ChoiceField(choices=[('1', 'One'), ('2', 'Two')], required=False) @@ -1041,22 +1148,36 @@ class FieldsTests(SimpleTestCase): self.assertEqual('', f.clean(None)) self.assertEqual('1', f.clean(1)) self.assertEqual('1', f.clean('1')) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", f.clean, '3') + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", + f.clean, '3' + ) def test_choicefield_3(self): f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')]) self.assertEqual('J', f.clean('J')) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. John is not one of the available choices.'", f.clean, 'John') + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. John is not one of the available choices.'", + f.clean, 'John' + ) def test_choicefield_4(self): - f = ChoiceField(choices=[('Numbers', (('1', 'One'), ('2', 'Two'))), ('Letters', (('3', 'A'), ('4', 'B'))), ('5', 'Other')]) + f = ChoiceField( + choices=[ + ('Numbers', (('1', 'One'), ('2', 'Two'))), + ('Letters', (('3', 'A'), ('4', 'B'))), ('5', 'Other'), + ] + ) self.assertEqual('1', f.clean(1)) self.assertEqual('1', f.clean('1')) self.assertEqual('3', f.clean(3)) self.assertEqual('3', f.clean('3')) self.assertEqual('5', f.clean(5)) self.assertEqual('5', f.clean('5')) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 6 is not one of the available choices.'", f.clean, '6') + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 6 is not one of the available choices.'", + f.clean, '6' + ) def test_choicefield_callable(self): choices = lambda: [('J', 'John'), ('P', 'Paul')] @@ -1093,7 +1214,10 @@ class FieldsTests(SimpleTestCase): def test_typedchoicefield_1(self): f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int) self.assertEqual(1, f.clean('1')) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 2 is not one of the available choices.'", f.clean, '2') + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 2 is not one of the available choices.'", + f.clean, '2' + ) def test_typedchoicefield_2(self): # Different coercion, same validation. @@ -1109,7 +1233,10 @@ class FieldsTests(SimpleTestCase): # Even more weirdness: if you have a valid choice but your coercion function # can't coerce, you'll still get a validation error. Don't do this! f = TypedChoiceField(choices=[('A', 'A'), ('B', 'B')], coerce=int) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. B is not one of the available choices.'", f.clean, 'B') + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. B is not one of the available choices.'", + f.clean, 'B' + ) # Required fields require values self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, '') @@ -1140,11 +1267,14 @@ class FieldsTests(SimpleTestCase): f = TypedChoiceField(choices=[(1, "1"), (2, "2")], coerce=coerce_func, required=True) self.assertEqual(Decimal('1.2'), f.clean('2')) - self.assertRaisesMessage(ValidationError, - "'This field is required.'", f.clean, '') - self.assertRaisesMessage(ValidationError, - "'Select a valid choice. 3 is not one of the available choices.'", - f.clean, '3') + self.assertRaisesMessage( + ValidationError, "'This field is required.'", + f.clean, '' + ) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", + f.clean, '3' + ) # NullBooleanField ############################################################ @@ -1168,7 +1298,11 @@ class FieldsTests(SimpleTestCase): hidden_nullbool1 = NullBooleanField(widget=HiddenInput, initial=True) hidden_nullbool2 = NullBooleanField(widget=HiddenInput, initial=False) f = HiddenNullBooleanForm() - self.assertHTMLEqual('', str(f)) + self.assertHTMLEqual( + '' + '', + str(f) + ) def test_nullbooleanfield_3(self): class HiddenNullBooleanForm(Form): @@ -1218,7 +1352,10 @@ class FieldsTests(SimpleTestCase): self.assertRaisesMessage(ValidationError, "'Enter a list of values.'", f.clean, 'hello') self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, []) self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, ()) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", f.clean, ['3']) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", + f.clean, ['3'] + ) def test_multiplechoicefield_2(self): f = MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two')], required=False) @@ -1232,18 +1369,29 @@ class FieldsTests(SimpleTestCase): self.assertRaisesMessage(ValidationError, "'Enter a list of values.'", f.clean, 'hello') self.assertEqual([], f.clean([])) self.assertEqual([], f.clean(())) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", f.clean, ['3']) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 3 is not one of the available choices.'", + f.clean, ['3'] + ) def test_multiplechoicefield_3(self): - f = MultipleChoiceField(choices=[('Numbers', (('1', 'One'), ('2', 'Two'))), ('Letters', (('3', 'A'), ('4', 'B'))), ('5', 'Other')]) + f = MultipleChoiceField( + choices=[('Numbers', (('1', 'One'), ('2', 'Two'))), ('Letters', (('3', 'A'), ('4', 'B'))), ('5', 'Other')] + ) self.assertEqual(['1'], f.clean([1])) self.assertEqual(['1'], f.clean(['1'])) self.assertEqual(['1', '5'], f.clean([1, 5])) self.assertEqual(['1', '5'], f.clean([1, '5'])) self.assertEqual(['1', '5'], f.clean(['1', 5])) self.assertEqual(['1', '5'], f.clean(['1', '5'])) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 6 is not one of the available choices.'", f.clean, ['6']) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 6 is not one of the available choices.'", f.clean, ['1', '6']) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 6 is not one of the available choices.'", + f.clean, ['6'] + ) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 6 is not one of the available choices.'", + f.clean, ['1', '6'] + ) def test_multiplechoicefield_changed(self): f = MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two'), ('3', 'Three')]) @@ -1262,7 +1410,10 @@ class FieldsTests(SimpleTestCase): def test_typedmultiplechoicefield_1(self): f = TypedMultipleChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int) self.assertEqual([1], f.clean(['1'])) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 2 is not one of the available choices.'", f.clean, ['2']) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 2 is not one of the available choices.'", + f.clean, ['2'] + ) def test_typedmultiplechoicefield_2(self): # Different coercion, same validation. @@ -1277,13 +1428,19 @@ class FieldsTests(SimpleTestCase): def test_typedmultiplechoicefield_4(self): f = TypedMultipleChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int) self.assertEqual([1, -1], f.clean(['1', '-1'])) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. 2 is not one of the available choices.'", f.clean, ['1', '2']) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. 2 is not one of the available choices.'", + f.clean, ['1', '2'] + ) def test_typedmultiplechoicefield_5(self): # Even more weirdness: if you have a valid choice but your coercion function # can't coerce, you'll still get a validation error. Don't do this! f = TypedMultipleChoiceField(choices=[('A', 'A'), ('B', 'B')], coerce=int) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. B is not one of the available choices.'", f.clean, ['B']) + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. B is not one of the available choices.'", + f.clean, ['B'] + ) # Required fields require values self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, []) @@ -1324,7 +1481,10 @@ class FieldsTests(SimpleTestCase): def test_combofield_1(self): f = ComboField(fields=[CharField(max_length=20), EmailField()]) self.assertEqual('test@example.com', f.clean('test@example.com')) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 28).'", f.clean, 'longemailaddress@example.com') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at most 20 characters (it has 28).'", + f.clean, 'longemailaddress@example.com' + ) self.assertRaisesMessage(ValidationError, "'Enter a valid email address.'", f.clean, 'not an email') self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, '') self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None) @@ -1332,7 +1492,10 @@ class FieldsTests(SimpleTestCase): def test_combofield_2(self): f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False) self.assertEqual('test@example.com', f.clean('test@example.com')) - self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 28).'", f.clean, 'longemailaddress@example.com') + self.assertRaisesMessage( + ValidationError, "'Ensure this value has at most 20 characters (it has 28).'", + f.clean, 'longemailaddress@example.com' + ) self.assertRaisesMessage(ValidationError, "'Enter a valid email address.'", f.clean, 'not an email') self.assertEqual('', f.clean('')) self.assertEqual('', f.clean(None)) @@ -1362,7 +1525,10 @@ class FieldsTests(SimpleTestCase): for exp, got in zip(expected, fix_os_paths(f.choices)): self.assertEqual(exp[1], got[1]) self.assertTrue(got[0].endswith(exp[0])) - self.assertRaisesMessage(ValidationError, "'Select a valid choice. fields.py is not one of the available choices.'", f.clean, 'fields.py') + self.assertRaisesMessage( + ValidationError, "'Select a valid choice. fields.py is not one of the available choices.'", + f.clean, 'fields.py' + ) assert fix_os_paths(f.clean(path + 'fields.py')).endswith('/django/forms/fields.py') def test_filepathfield_3(self): @@ -1437,24 +1603,36 @@ class FieldsTests(SimpleTestCase): from django.forms.widgets import SplitDateTimeWidget f = SplitDateTimeField() self.assertIsInstance(f.widget, SplitDateTimeWidget) - self.assertEqual(datetime.datetime(2006, 1, 10, 7, 30), f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)])) + self.assertEqual( + datetime.datetime(2006, 1, 10, 7, 30), + f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) + ) self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None) self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, '') self.assertRaisesMessage(ValidationError, "'Enter a list of values.'", f.clean, 'hello') - six.assertRaisesRegex(self, ValidationError, "'Enter a valid date\.', u?'Enter a valid time\.'", f.clean, ['hello', 'there']) + six.assertRaisesRegex( + self, ValidationError, "'Enter a valid date\.', u?'Enter a valid time\.'", + f.clean, ['hello', 'there'] + ) self.assertRaisesMessage(ValidationError, "'Enter a valid time.'", f.clean, ['2006-01-10', 'there']) self.assertRaisesMessage(ValidationError, "'Enter a valid date.'", f.clean, ['hello', '07:30']) def test_splitdatetimefield_2(self): f = SplitDateTimeField(required=False) - self.assertEqual(datetime.datetime(2006, 1, 10, 7, 30), f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)])) + self.assertEqual( + datetime.datetime(2006, 1, 10, 7, 30), + f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) + ) self.assertEqual(datetime.datetime(2006, 1, 10, 7, 30), f.clean(['2006-01-10', '07:30'])) self.assertIsNone(f.clean(None)) self.assertIsNone(f.clean('')) self.assertIsNone(f.clean([''])) self.assertIsNone(f.clean(['', ''])) self.assertRaisesMessage(ValidationError, "'Enter a list of values.'", f.clean, 'hello') - six.assertRaisesRegex(self, ValidationError, "'Enter a valid date\.', u?'Enter a valid time\.'", f.clean, ['hello', 'there']) + six.assertRaisesRegex( + self, ValidationError, "'Enter a valid date\.', u?'Enter a valid time\.'", + f.clean, ['hello', 'there'] + ) self.assertRaisesMessage(ValidationError, "'Enter a valid time.'", f.clean, ['2006-01-10', 'there']) self.assertRaisesMessage(ValidationError, "'Enter a valid date.'", f.clean, ['hello', '07:30']) self.assertRaisesMessage(ValidationError, "'Enter a valid time.'", f.clean, ['2006-01-10', '']) @@ -1489,7 +1667,10 @@ class FieldsTests(SimpleTestCase): self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '12345:2:3:4') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1::2:3::4') - self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, 'foo::223:6cff:fe8a:2e8a') + self.assertRaisesMessage( + ValidationError, "'This is not a valid IPv6 address.'", + f.clean, 'foo::223:6cff:fe8a:2e8a' + ) self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1::2:3:4:5:6:7:8') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1:2') @@ -1518,7 +1699,10 @@ class FieldsTests(SimpleTestCase): self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '12345:2:3:4') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1::2:3::4') - self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, 'foo::223:6cff:fe8a:2e8a') + self.assertRaisesMessage( + ValidationError, "'This is not a valid IPv6 address.'", + f.clean, 'foo::223:6cff:fe8a:2e8a' + ) self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1::2:3:4:5:6:7:8') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1:2') @@ -1535,7 +1719,10 @@ class FieldsTests(SimpleTestCase): self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '12345:2:3:4') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1::2:3::4') - self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, 'foo::223:6cff:fe8a:2e8a') + self.assertRaisesMessage( + ValidationError, "'This is not a valid IPv6 address.'", + f.clean, 'foo::223:6cff:fe8a:2e8a' + ) self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1::2:3:4:5:6:7:8') self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'", f.clean, '1:2') diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index d8cdabae2d..ac96d775a2 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -58,9 +58,18 @@ class FormsTestCase(SimpleTestCase): self.assertEqual(p.cleaned_data["first_name"], 'John') self.assertEqual(p.cleaned_data["last_name"], 'Lennon') self.assertEqual(p.cleaned_data["birthday"], datetime.date(1940, 10, 9)) - self.assertHTMLEqual(str(p['first_name']), '') - self.assertHTMLEqual(str(p['last_name']), '') - self.assertHTMLEqual(str(p['birthday']), '') + self.assertHTMLEqual( + str(p['first_name']), + '' + ) + self.assertHTMLEqual( + str(p['last_name']), + '' + ) + self.assertHTMLEqual( + str(p['birthday']), + '' + ) nonexistenterror = "Key u?'nonexistentfield' not found in 'Person'" with six.assertRaisesRegex(self, KeyError, nonexistenterror): @@ -72,9 +81,12 @@ class FormsTestCase(SimpleTestCase): for boundfield in p: form_output.append(str(boundfield)) - self.assertHTMLEqual('\n'.join(form_output), """ + self.assertHTMLEqual( + '\n'.join(form_output), + """ -""") +""" + ) form_output = [] @@ -86,9 +98,15 @@ class FormsTestCase(SimpleTestCase): ['Last name', 'Lennon'], ['Birthday', '1940-10-9'] ]) - self.assertHTMLEqual(str(p), """ - -""") + self.assertHTMLEqual( + str(p), + """ + + + + +""" + ) def test_empty_dict(self): # Empty dictionaries are valid, too. @@ -99,21 +117,54 @@ class FormsTestCase(SimpleTestCase): self.assertEqual(p.errors['birthday'], ['This field is required.']) self.assertFalse(p.is_valid()) self.assertEqual(p.cleaned_data, {}) - self.assertHTMLEqual(str(p), """
        • This field is required.
        -
        • This field is required.
        -
        • This field is required.
        """) - self.assertHTMLEqual(p.as_table(), """
        • This field is required.
        -
        • This field is required.
        -
        • This field is required.
        """) - self.assertHTMLEqual(p.as_ul(), """
        • This field is required.
      • -
        • This field is required.
      • -
        • This field is required.
      • """) - self.assertHTMLEqual(p.as_p(), """
        • This field is required.
        -

        + self.assertHTMLEqual( + str(p), + """
        • This field is required.
        -

        + + +
        • This field is required.
        + +
        • This field is required.
        -

        """) +""" + ) + self.assertHTMLEqual( + p.as_table(), + """ +
        • This field is required.
        + + +
        • This field is required.
        + + +
        • This field is required.
        +""" + ) + self.assertHTMLEqual( + p.as_ul(), + """
        • This field is required.
        + +
      • +
        • This field is required.
        + +
      • +
        • This field is required.
        + +
      • """ + ) + self.assertHTMLEqual( + p.as_p(), + """
        • This field is required.
        +

        +

        +
        • This field is required.
        +

        +

        +
        • This field is required.
        +

        +

        """ + ) def test_unbound_form(self): # If you don't pass any values to the Form's __init__(), or if you pass None, @@ -128,34 +179,96 @@ class FormsTestCase(SimpleTestCase): self.fail('Attempts to access cleaned_data when validation fails should fail.') except AttributeError: pass - self.assertHTMLEqual(str(p), """ - -""") - self.assertHTMLEqual(p.as_table(), """ - -""") - self.assertHTMLEqual(p.as_ul(), """
      • -
      • -
      • """) - self.assertHTMLEqual(p.as_p(), """

        -

        -

        """) + self.assertHTMLEqual( + str(p), + """ + + + + +""" + ) + self.assertHTMLEqual( + p.as_table(), + """ + + + + +""" + ) + self.assertHTMLEqual( + p.as_ul(), + """
      • +
      • +
      • +
      • +
      • +
      • """ + ) + self.assertHTMLEqual( + p.as_p(), + """

        +

        +

        +

        +

        +

        """ + ) def test_unicode_values(self): # Unicode values are handled properly. - p = Person({'first_name': 'John', 'last_name': '\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9'}) - self.assertHTMLEqual(p.as_table(), '\n\n') - self.assertHTMLEqual(p.as_ul(), '
      • \n
      • \n
      • ') - self.assertHTMLEqual(p.as_p(), '

        \n

        \n

        ') + p = Person({ + 'first_name': 'John', + 'last_name': '\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', + 'birthday': '1940-10-9' + }) + self.assertHTMLEqual( + p.as_table(), + '' + '\n' + '' + '\n' + '' + '' + ) + self.assertHTMLEqual( + p.as_ul(), + '
      • ' + '
      • \n' + '
      • ' + '
      • \n' + '
      • ' + '
      • ' + ) + self.assertHTMLEqual( + p.as_p(), + '

        ' + '

        \n' + '

        ' + '

        \n' + '

        ' + '

        ' + ) p = Person({'last_name': 'Lennon'}) self.assertEqual(p.errors['first_name'], ['This field is required.']) self.assertEqual(p.errors['birthday'], ['This field is required.']) self.assertFalse(p.is_valid()) - self.assertDictEqual(p.errors, {'birthday': ['This field is required.'], 'first_name': ['This field is required.']}) + self.assertDictEqual( + p.errors, + {'birthday': ['This field is required.'], 'first_name': ['This field is required.']} + ) self.assertEqual(p.cleaned_data, {'last_name': 'Lennon'}) self.assertEqual(p['first_name'].errors, ['This field is required.']) - self.assertHTMLEqual(p['first_name'].errors.as_ul(), '
        • This field is required.
        ') + self.assertHTMLEqual( + p['first_name'].errors.as_ul(), + '
        • This field is required.
        ' + ) self.assertEqual(p['first_name'].errors.as_text(), '* This field is required.') p = Person() @@ -168,7 +281,13 @@ class FormsTestCase(SimpleTestCase): # Form, even if you pass extra data when you define the Form. In this # example, we pass a bunch of extra fields to the form constructor, # but cleaned_data contains only the form's fields. - data = {'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9', 'extra1': 'hello', 'extra2': 'hello'} + data = { + 'first_name': 'John', + 'last_name': 'Lennon', + 'birthday': '1940-10-9', + 'extra1': 'hello', + 'extra2': 'hello', + } p = Person(data) self.assertTrue(p.is_valid()) self.assertEqual(p.cleaned_data['first_name'], 'John') @@ -212,47 +331,84 @@ class FormsTestCase(SimpleTestCase): # into which the field's name will be inserted. It will also put a
      """) +
    """ + ) # When RadioSelect is used with auto_id, and the whole form is printed using # either as_table() or as_ul(), the label for the RadioSelect will point to the # ID of the *first* radio button. - self.assertHTMLEqual(f.as_table(), """ + self.assertHTMLEqual( + f.as_table(), + """
    • -
    """) - self.assertHTMLEqual(f.as_ul(), """
  • +""" + ) + self.assertHTMLEqual( + f.as_ul(), + """
    • -
  • """) - self.assertHTMLEqual(f.as_p(), """

    +""" + ) + self.assertHTMLEqual( + f.as_p(), + """

    """) +

    """ + ) # Test iterating on individual radios in a template t = Template('{% for radio in form.language %}
    {{ radio }}
    {% endfor %}') - self.assertHTMLEqual(t.render(Context({'form': f})), """
    """ + ) def test_form_with_iterable_boundfield(self): class BeatleForm(Form): - name = ChoiceField(choices=[('john', 'John'), ('paul', 'Paul'), ('george', 'George'), ('ringo', 'Ringo')], widget=RadioSelect) + name = ChoiceField( + choices=[('john', 'John'), ('paul', 'Paul'), ('george', 'George'), ('ringo', 'Ringo')], + widget=RadioSelect, + ) f = BeatleForm(auto_id=False) - self.assertHTMLEqual('\n'.join(str(bf) for bf in f['name']), """ + self.assertHTMLEqual( + '\n'.join(str(bf) for bf in f['name']), + """ -""") - self.assertHTMLEqual('\n'.join('
    %s
    ' % bf for bf in f['name']), """
    +""" + ) + self.assertHTMLEqual( + '\n'.join('
    %s
    ' % bf for bf in f['name']), + """
    -
    """) +
    """ + ) def test_form_with_noniterable_boundfield(self): # You can iterate over any BoundField, not just those with widget=RadioSelect. @@ -552,14 +738,25 @@ class FormsTestCase(SimpleTestCase): f = MessageForm({'when_0': '1992-01-01', 'when_1': '01:01'}) self.assertTrue(f.is_valid()) - self.assertHTMLEqual(str(f['when']), '') - self.assertHTMLEqual(f['when'].as_hidden(), '') + self.assertHTMLEqual( + str(f['when']), + '' + '' + ) + self.assertHTMLEqual( + f['when'].as_hidden(), + '' + '' + ) def test_mulitple_choice_checkbox(self): # MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. class SongForm(Form): name = CharField() - composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple) + composers = MultipleChoiceField( + choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], + widget=CheckboxSelectMultiple, + ) f = SongForm(auto_id=False) self.assertHTMLEqual(str(f['composers']), """