Merge branch 'feature/migration-tests' of https://github.com/takeflight/wagtail into takeflight-feature/migration-tests

Conflicts:
	wagtail/wagtailsnippets/tests.py
pull/845/head
Matt Westcott 2014-12-02 11:45:29 +00:00
commit 3535b5ca21
7 zmienionych plików z 196 dodań i 13 usunięć

Wyświetl plik

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('tests', '0006_merge'),
]
operations = [
migrations.CreateModel(
name='RegisterDecorator',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
],
options={
},
bases=(models.Model,),
),
]

Wyświetl plik

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('tests', '0007_registerdecorator'),
]
operations = [
migrations.AlterField(
model_name='pagechoosermodel',
name='page',
field=models.ForeignKey(help_text='help text', to='wagtailcore.Page'),
preserve_default=True,
),
migrations.AlterField(
model_name='snippetchoosermodel',
name='advert',
field=models.ForeignKey(help_text='help text', to='tests.Advert'),
preserve_default=True,
),
]

Wyświetl plik

@ -497,3 +497,8 @@ class SnippetChooserModel(models.Model):
panels = [
SnippetChooserPanel('advert', Advert),
]
@register_snippet
class RegisterDecorator(models.Model):
pass

Wyświetl plik

@ -0,0 +1,129 @@
"""
Check that all changes to Wagtail models have had migrations created. If there
are outstanding model changes that need migrations, fail the tests.
"""
from django import VERSION
from django.test import TransactionTestCase
from django.utils.six import iteritems
import south.management.commands.schemamigration
try:
from unittest import skipIf, skipUnless
except ImportError:
from django.utils.unittest import skipIf, skipUnless
class TestForMigrations(TransactionTestCase):
@skipIf(VERSION < (1, 7), "Migrations introduced in Django 1.7")
def test_django_17_migrations(self):
from django.apps import apps
from django.db.migrations.loader import MigrationLoader
from django.db.migrations.autodetector import MigrationAutodetector
from django.db.migrations.state import ProjectState
from django.db.migrations.questioner import MigrationQuestioner
app_labels = set(app.label for app in apps.get_app_configs()
if app.name.startswith('wagtail.'))
for app_label in app_labels:
apps.get_app_config(app_label.split('.')[-1])
loader = MigrationLoader(None, ignore_no_migrations=True)
conflicts = dict(
(app_label, conflict)
for app_label, conflict in iteritems(loader.detect_conflicts())
if app_label in app_labels
)
if conflicts:
name_str = "; ".join("%s in %s" % (", ".join(names), app)
for app, names in conflicts.items())
self.fail("Conflicting migrations detected (%s)." % name_str)
autodetector = MigrationAutodetector(
loader.project_state(),
ProjectState.from_apps(apps),
MigrationQuestioner(specified_apps=app_labels, dry_run=True),
)
changes = autodetector.changes(
graph=loader.graph,
trim_to_apps=app_labels or None,
convert_apps=app_labels or None,
)
if changes:
apps = ', '.join(apps.get_app_config(label).name
for label in changes.keys())
migrations = '\n'.join((
' {migration}\n{changes}'.format(
migration=migration,
changes='\n'.join(' {0}'.format(operation.describe())
for operation in migration.operations))
for (_, migrations) in changes.items()
for migration in migrations))
self.fail('Model changes with no migrations detected:\n%s' % migrations)
@skipUnless(VERSION < (1, 7), "South migrations used for Django < 1.7")
def test_south_migrations(self):
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
from django.db import models
from south.migration import Migrations, migrate_app
from south.models import MigrationHistory
from south.exceptions import NoMigrations
from south.creator import changes, actions, freezer
from south.management.commands.datamigration import Command as DataCommand
apps = [app for app in settings.INSTALLED_APPS
if app.startswith('wagtail.')]
failing_apps = []
for app_name in apps:
app = app_name.split('.')[-1]
try:
models.get_app(app)
except ImproperlyConfigured:
# This module fails to load, probably because it has no
# models.py. Ignore it and move on
continue
try:
migrations = Migrations(app, force_creation=False, verbose_creation=False)
last_migration = migrations[-1]
except (NoMigrations, IndexError):
# No migrations for this app, probably doesnt have models
continue
if migrations.app_label() not in getattr(last_migration.migration_class(), "complete_apps", []):
self.fail("Automatic migrations checking failed, since the previous migration does not have this whole app frozen.\nEither make migrations using '--freeze %s' or set 'SOUTH_AUTO_FREEZE_APP = True' in your settings.py." % migrations.app_label())
# Alright, construct two model dicts to run the differ on.
old_defs = dict(
(k, v) for k, v in last_migration.migration_class().models.items()
if k.split(".")[0] == migrations.app_label()
)
new_defs = dict(
(k, v) for k, v in freezer.freeze_apps([migrations.app_label()]).items()
if k.split(".")[0] == migrations.app_label()
)
change_source = changes.AutoChanges(
migrations = migrations,
old_defs = old_defs,
old_orm = last_migration.orm(),
new_defs = new_defs,
)
name = 'test'
# Get the actions, and then insert them into the actions lists
if list(change_source.get_changes()):
failing_apps.append(app_name)
if failing_apps:
self.fail('Model changes with no South migration detected in apps: %s' % (
', '.join(failing_apps)))

Wyświetl plik

@ -6,6 +6,8 @@ from south.db import db
from south.v2 import SchemaMigration
from django.db import models
from wagtail.wagtailcore.compat import AUTH_USER_MODEL, AUTH_USER_MODEL_NAME
class Migration(SchemaMigration):
@ -79,8 +81,8 @@ class Migration(SchemaMigration):
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
AUTH_USER_MODEL: {
'Meta': {'object_name': AUTH_USER_MODEL_NAME},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
@ -118,7 +120,7 @@ class Migration(SchemaMigration):
'height': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uploaded_by_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'uploaded_by_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % AUTH_USER_MODEL, 'null': 'True', 'blank': 'True'}),
'width': ('django.db.models.fields.IntegerField', [], {})
},
'wagtailimages.rendition': {
@ -133,4 +135,4 @@ class Migration(SchemaMigration):
}
}
complete_apps = ['wagtailimages']
complete_apps = ['wagtailimages']

Wyświetl plik

@ -6,6 +6,8 @@ from south.db import db
from south.v2 import SchemaMigration
from django.db import models
from wagtail.wagtailcore.compat import AUTH_USER_MODEL, AUTH_USER_MODEL_NAME
class Migration(SchemaMigration):
@ -39,8 +41,8 @@ class Migration(SchemaMigration):
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
AUTH_USER_MODEL: {
'Meta': {'object_name': AUTH_USER_MODEL_NAME},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
@ -78,7 +80,7 @@ class Migration(SchemaMigration):
'height': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uploaded_by_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'uploaded_by_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % AUTH_USER_MODEL, 'null': 'True', 'blank': 'True'}),
'width': ('django.db.models.fields.IntegerField', [], {})
},
'wagtailimages.rendition': {
@ -93,4 +95,4 @@ class Migration(SchemaMigration):
}
}
complete_apps = ['wagtailimages']
complete_apps = ['wagtailimages']

Wyświetl plik

@ -4,7 +4,7 @@ from django.db import models
from wagtail.tests.utils import WagtailTestUtils
from django.test.utils import override_settings
from wagtail.tests.models import Advert, AlphaSnippet, ZuluSnippet, SnippetChooserModel
from wagtail.tests.models import Advert, AlphaSnippet, ZuluSnippet, SnippetChooserModel, RegisterDecorator
from wagtail.wagtailsnippets.models import register_snippet, SNIPPET_MODELS
from wagtail.wagtailsnippets.views.snippets import (
@ -189,10 +189,6 @@ class TestSnippetRegistering(TestCase):
self.assertIn(RegisterFunction, SNIPPET_MODELS)
def test_register_decorator(self):
@register_snippet
class RegisterDecorator(models.Model):
pass
# Misbehaving decorators often return None
self.assertIsNotNone(RegisterDecorator)
self.assertIn(RegisterDecorator, SNIPPET_MODELS)