Exemplo n.º 1
0
    def handle(self,
               app=None,
               name="",
               freeze_list=None,
               stdout=False,
               verbosity=1,
               **options):

        # Any supposed lists that are None become empty lists
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"

        # Only allow valid names
        if re.search('[^_\w]', name) and name != "-":
            self.error(
                "Migration names should contain only alphanumeric characters and underscores."
            )

        # if not name, there's an error
        if not name:
            self.error("You must provide a name for this migration\n" +
                       self.usage_str)

        if not app:
            self.error("You must provide an app to create a migration for.\n" +
                       self.usage_str)

        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app,
                                force_creation=True,
                                verbose_creation=verbosity > 0)

        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)

        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)

        # So, what's in this file, then?
        file_contents = MIGRATION_TEMPLATE % {
            "frozen_models":
            freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps":
            apps_to_freeze and "complete_apps = [%s]" %
            (", ".join(map(repr, apps_to_freeze))) or ""
        }

        # - is a special name which means 'print to stdout'
        if name == "-":
            print(file_contents)
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename),
                      "w")
            fp.write(file_contents)
            fp.close()
            print("Created %s." % new_filename, file=sys.stderr)
Exemplo n.º 2
0
    def handle(self, **options):

        # Resolve dependencies
        Migrations.calculate_dependencies()

        print "digraph G {"

        # Print each app in a cluster
        #for migrations in all_migrations():
        #    print "  subgraph %s {" % migrations.app_label()
        #    # Nodes inside here are linked
        #    print (" -> ".join(['"%s.%s"' % (migration.app_label(), migration.name()) for migration in migrations])) + ";"
        #    print "  }"

        # For every migration, print its links.
        for migrations in all_migrations():
            for migration in migrations:
                for other in migration.dependencies:
                    print '"%s.%s" -> "%s.%s"' % (
                        other.app_label(),
                        other.name(),
                        migration.app_label(),
                        migration.name(),
                    )

        print "}"
Exemplo n.º 3
0
def skip_migration_if_applied(settings,
                              app_name,
                              table_name,
                              name="0001_initial"):
    from south.migration import Migrations
    from sentry.utils.db import table_exists
    import types

    if app_name not in settings.INSTALLED_APPS:
        return

    migration = Migrations(app_name)[name]

    def skip_if_table_exists(original):
        def wrapped(self):
            # TODO: look into why we're having to return some ridiculous
            # lambda
            if table_exists(table_name):
                return lambda x=None: None
            return original()

        wrapped.__name__ = original.__name__
        return wrapped

    migration.forwards = types.MethodType(
        skip_if_table_exists(migration.forwards), migration)
Exemplo n.º 4
0
    def setUp(self):
        super(MigrationTest, self).setUp()

        self.before_migrations = []
        for app_name, version in self.before:
            migrations = Migrations(app_name)
            self.before_migrations.append(
                (app_name,
                 migrations.guess_migration(
                     self._get_migration_number(version)).name()))
        self.after_migrations = []
        for app_name, version in self.after:
            migrations = Migrations(app_name)
            self.after_migrations.append(
                (app_name,
                 migrations.guess_migration(
                     self._get_migration_number(version)).name()))

        self.before_orm = {}
        for app_name, version in self.before_migrations:
            migrations = Migrations(app_name)
            self.before_orm[app_name] = migrations[version].orm()
        self.after_orm = {}
        for app_name, version in self.after_migrations:
            migrations = Migrations(app_name)
            self.after_orm[app_name] = migrations[version].orm()

        for app_name, version in self.before_migrations:
            # Do a fake migration first to update the migration history.
            self.migrate(app_name, version=None, fake=True)
            self.migrate(app_name, version=version)
Exemplo n.º 5
0
    def handle(self, app=None, *args, **options):

        # Make sure we have an app
        if not app:
            print "Please specify an app to convert."
            return

        # See if the app exists
        app = app.split(".")[-1]
        try:
            app_module = models.get_app(app)
        except ImproperlyConfigured:
            print "There is no enabled application matching '%s'." % app
            return

        # Try to get its list of models
        model_list = models.get_models(app_module)
        if not model_list:
            print "This application has no models; this command is for applications that already have models syncdb'd."
            print "Make some models, and then use ./manage.py schemamigration %s --initial instead." % app
            return

        # Ask South if it thinks it's already got migrations
        try:
            Migrations(app)
        except NoMigrations:
            pass
        else:
            print "This application is already managed by South."
            return

        # Finally! It seems we've got a candidate, so do the two-command trick
        verbosity = int(options.get('verbosity', 0))
        management.call_command("schemamigration",
                                app,
                                initial=True,
                                verbosity=verbosity)

        # Now, we need to re-clean and sanitise appcache
        hacks.clear_app_cache()
        hacks.repopulate_app_cache()

        # And also clear our cached Migration classes
        Migrations._clear_cache()

        # Now, migrate
        management.call_command(
            "migrate",
            app,
            "0001",
            fake=True,
            verbosity=verbosity,
            ignore_ghosts=options.get("ignore_ghosts", False),
            delete_ghosts=options.get("delete_ghosts", False),
        )

        print
        print "App '%s' converted. Note that South assumed the application's models matched the database" % app
        print "(i.e. you haven't changed it since last syncdb); if you have, you should delete the %s/migrations" % app
        print "directory, revert models.py so it matches the database, and try again."
Exemplo n.º 6
0
    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)))
 def handle(self, app=None, *args, **options):
     
     # Make sure we have an app
     if not app:
         print("Please specify an app to convert.")
         return
     
     # See if the app exists
     app = app.split(".")[-1]
     try:
         app_module = models.get_app(app)
     except ImproperlyConfigured:
         print("There is no enabled application matching '%s'." % app)
         return
     
     # Try to get its list of models
     model_list = models.get_models(app_module)
     if not model_list:
         print("This application has no models; this command is for applications that already have models syncdb'd.")
         print("Make some models, and then use ./manage.py schemamigration %s --initial instead." % app)
         return
     
     # Ask South if it thinks it's already got migrations
     try:
         Migrations(app)
     except NoMigrations:
         pass
     else:
         print("This application is already managed by South.")
         return
     
     # Finally! It seems we've got a candidate, so do the two-command trick
     verbosity = int(options.get('verbosity', 0))
     management.call_command("schemamigration", app, initial=True, verbosity=verbosity)
     
     # Now, we need to re-clean and sanitise appcache
     hacks.clear_app_cache()
     hacks.repopulate_app_cache()
     
     # And also clear our cached Migration classes
     Migrations._clear_cache()
     
     # Now, migrate
     management.call_command(
         "migrate",
         app,
         "0001",
         fake=True,
         verbosity=verbosity,
         ignore_ghosts=options.get("ignore_ghosts", False),
         delete_ghosts=options.get("delete_ghosts", False),
     )
     
     print() 
     print("App '%s' converted. Note that South assumed the application's models matched the database" % app)
     print("(i.e. you haven't changed it since last syncdb); if you have, you should delete the %s/migrations" % app)
     print("directory, revert models.py so it matches the database, and try again.")
Exemplo n.º 8
0
def _south_migrate_all():
    if not 'south' in settings.INSTALLED_APPS:
        sys.stderr.write(
            "warning: 'south' is not in INSTALLED_APPS, no migration done.\n")
        return 0
    #pylint: disable=import-error,too-many-nested-blocks
    from south.migration import Migrations
    from south.management.commands import migrate
    schema_cmd = SchemaMigration()
    initial_apps = []
    auto_apps = [] #pylint: disable=unused-variable
    for app in [app for app in settings.INSTALLED_APPS if app != 'south']:
        try:
            app_module = models.get_app(app) #pylint: disable=no-member
                                             # South only used with Django < 1.7
            clsmembers = inspect.getmembers(app_module, is_model_class)
            if clsmembers:
                migrations_dir = os.path.join(
                    os.path.dirname(app_module.__file__), 'migrations')
                if os.path.isdir(migrations_dir):
                    schema_cmd.handle(app, auto=True)#pylint:disable=no-member
                    found = False
                    for migration_file in os.listdir(migrations_dir):
                        if (re.match(r'^\d\d\d\d', migration_file)
                            and not migration_file.startswith('0001_initial')):
                            found = True
                            break
                    if found:
                        auto_apps += [app]
                    else:
                        initial_apps += [app]
                else:
                    schema_cmd.handle( #pylint:disable=no-member
                        app, initial=True)
                    initial_apps += [app]
            else:
                sys.stderr.write(
                    "warning: App %s does not seem to contain any Model\n" %
                    app)
        except OSError as err:
            sys.stderr.write("error: App %s, %s\n" % (app, err))
        except RuntimeError as err:
            sys.stderr.write("error: App %s, %s\n" % (app, err))
        except ImproperlyConfigured:
            sys.stderr.write(
                "warning: App %s does not seem to contain a models.py\n" % app)

    # Clear the cached Migrations instances now that we have more of them.
    Migrations._clear_cache() #pylint: disable=no-member,protected-access
    migrate_cmd = migrate.Command()
    for app in initial_apps:
        sys.stderr.write("initial migrate for %s\n" % app)
        migrate_cmd.handle(app, fake=True)
    sys.stderr.write("MIGRATE ALL!\n")
    migrate_cmd.handle(no_initial_data=True)
    return 0
Exemplo n.º 9
0
    def get_indexes(self):
        # TODO: не удаляются индексы у внешних ключей и добавочные
        # _like-индексы к ним. Например у House
        migration = Migrations('fias', force_creation=True)
        # получим текущее состояние базы
        new_defs = dict(
            (k, v)
            for k, v in freezer.freeze_apps([migration.app_label()]).items()
            if k.split(".")[0] == migration.app_label())
        # скопируем и удалим все индексы
        old_defs = copy.deepcopy(new_defs)
        for table in old_defs.values():
            for key, value in table.items():
                # удалим 'index_together'
                if key == 'Meta' and 'index_together' in value:
                    del value['index_together']
                if isinstance(value, tuple):
                    # удалим 'unique'
                    if 'unique' in value[2]:
                        value[2]['unique'] = False
                    # удалим 'db_index'
                    if 'db_index' in value[2]:
                        value[2]['db_index'] = False

        class InitialMigration(SchemaMigration):
            def forwards(self, orm):
                pass

            def backwards(self, orm):
                pass

            models = old_defs
            complete_apps = ['fias']

        initial_orm = FakeORM(InitialMigration, "fias")

        # получим все изменения, т.е. список индексов
        change_source = changes.AutoChanges(
            migrations=migration,
            old_defs=old_defs,
            old_orm=initial_orm,
            new_defs=new_defs,
        )

        for action_name, params in change_source.get_changes():
            try:
                action_class = getattr(actions, action_name)
            except AttributeError:
                raise ValueError("Invalid action name from source: %s" %
                                 action_name)
            else:
                if issubclass(action_class, AddUnique):
                    yield action_class, params
Exemplo n.º 10
0
    def handle(self, app=None, name="", freeze_list=None, stdout=False, verbosity=1, **options):

        verbosity = int(verbosity)
        
        # Any supposed lists that are None become empty lists
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"
	
        # Only allow valid names
        if re.search('[^_\w]', name) and name != "-":
            self.error("Migration names should contain only alphanumeric characters and underscores.")
        
        # If not name, there's an error
        if not name:
            self.error("You must provide a name for this migration.\n" + self.usage_str)
        
        if not app:
            self.error("You must provide an app to create a migration for.\n" + self.usage_str)

        # Ensure that verbosity is not a string (Python 3)
        try:
            verbosity = int(verbosity)
        except ValueError:
            self.error("Verbosity must be an number.\n" + self.usage_str)
            
        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app, force_creation=True, verbose_creation=verbosity > 0)
        
        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)
        
        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)
        
        # So, what's in this file, then?
        file_contents = self.get_migration_template() % {
            "frozen_models":  freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps": apps_to_freeze and "complete_apps = [%s]" % (", ".join(map(repr, apps_to_freeze))) or ""
        }
        
        # - is a special name which means 'print to stdout'
        if name == "-":
            print(file_contents)
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename), "w")
            fp.write(file_contents)
            fp.close()
            print("Created %s." % new_filename, file=sys.stderr)
Exemplo n.º 11
0
    def testGenerateSouthMigration(self):
        tmp = StringIO.StringIO()
        sys.stdout = tmp
        sys.stderr = tmp

        management.call_command(
            "schemamigration",
            "arm_access_support",
            "-",
            initial=True,
        )
        migrations = Migrations("arm_access_support")
        shutil.rmtree(migrations.migrations_dir())

        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
Exemplo n.º 12
0
def migratable(app):
    try:
        if south_ok:
            Migrations(app)
            return True
    except (NoMigrations, ImproperlyConfigured):
        pass
    return False
def get_migrations():
    "Clears migration cache and gets migrations for the test app"
    from south.migration import Migrations

    clear_migrations()
    return Migrations(
        tagulous_tests_migration, force_creation=True, verbose_creation=False
    )
Exemplo n.º 14
0
    def handle(self, **options):

        # Resolve dependencies
        Migrations.calculate_dependencies()

        colors = ['crimson', 'darkgreen', 'darkgoldenrod', 'navy',
                  'brown', 'darkorange', 'aquamarine', 'blueviolet']
        color_index = 0
        wrapper = textwrap.TextWrapper(width=40)

        print("digraph G {")

        # Group each app in a subgraph
        for migrations in all_migrations():
            print("  subgraph %s {" % migrations.app_label())
            print("    node [color=%s];" % colors[color_index])
            for migration in migrations:
                # Munge the label - text wrap and change _ to spaces
                label = "%s - %s" % (
                        migration.app_label(), migration.name())
                label = re.sub(r"_+", " ", label)
                label = "\\n".join(wrapper.wrap(label))
                print('    "%s.%s" [label="%s"];' % (
                    migration.app_label(), migration.name(), label))
            print("  }")
            color_index = (color_index + 1) % len(colors)

        # For every migration, print its links.
        for migrations in all_migrations():
            for migration in migrations:
                for other in migration.dependencies:
                    # Added weight tends to keep migrations from the same app
                    # in vertical alignment
                    attrs = "[weight=2.0]"
                    # But the more interesting edges are those between apps
                    if other.app_label() != migration.app_label():
                        attrs = "[style=bold]"
                    print('  "%s.%s" -> "%s.%s" %s;' % (
                        other.app_label(), other.name(),
                        migration.app_label(), migration.name(),
                        attrs
                    ))

        print("}");
Exemplo n.º 15
0
    def handle(self, **options):
        
        # Resolve dependencies
        Migrations.calculate_dependencies()

        colors = [ 'crimson', 'darkgreen', 'darkgoldenrod', 'navy',
                'brown', 'darkorange', 'aquamarine' , 'blueviolet' ]
        color_index = 0
        wrapper = textwrap.TextWrapper(width=40)
        
        print("digraph G {")
        
        # Group each app in a subgraph
        for migrations in all_migrations():
            print("  subgraph %s {" % migrations.app_label())
            print("    node [color=%s];" % colors[color_index])
            for migration in migrations:
                # Munge the label - text wrap and change _ to spaces
                label = "%s - %s" % (
                        migration.app_label(), migration.name())
                label = re.sub(r"_+", " ", label)
                label=  "\\n".join(wrapper.wrap(label))
                print('    "%s.%s" [label="%s"];' % (
                        migration.app_label(), migration.name(), label))
            print("  }")
            color_index = (color_index + 1) % len(colors)

        # For every migration, print its links.
        for migrations in all_migrations():
            for migration in migrations:
                for other in migration.dependencies:
                    # Added weight tends to keep migrations from the same app
                    # in vertical alignment
                    attrs = "[weight=2.0]"
                    # But the more interesting edges are those between apps
                    if other.app_label() != migration.app_label():
                        attrs = "[style=bold]"
                    print('  "%s.%s" -> "%s.%s" %s;' % (
                        other.app_label(), other.name(),
                        migration.app_label(), migration.name(),
                        attrs
                    ))
            
        print("}");
Exemplo n.º 16
0
    def handle(self, app=None, name="", freeze_list=None, stdout=False, verbosity=1, **options):
        # Any supposed lists that are None become empty lists
        freeze_list = freeze_list or []
        fixtures = options.get('fixtures', ['blogs.json'])
        # --stdout means name = -
        if options.get('stdout', None):
            name = "-"

        # Only allow valid names
        if re.search('[^_\w]', name) and name != "-":
            self.error("Migration names should contain only alphanumeric characters and underscores.")

        # if not name, there's an error
        if not name:
            self.error("You must provide a name for this migration\n" + self.usage_str)

        if not app:
            self.error("You must provide an app to create a migration for.\n" + self.usage_str)

        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app, force_creation=True, verbose_creation=verbosity > 0)

        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)

        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)

        # So, what's in this file, then?
        file_contents = MIGRATION_TEMPLATE % {
            "fixutres": ",".join(fixtures),
            "frozen_models":  freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps": apps_to_freeze and "complete_apps = [%s]" % (", ".join(map(repr, apps_to_freeze))) or ""
        }

        # - is a special name which means 'print to stdout'
        if name == "-":
            print file_contents
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename), "w")
            fp.write(file_contents)
            fp.close()
            print >>sys.stderr, "Created %s." % new_filename
Exemplo n.º 17
0
def skip_migration_if_applied(settings, app_name, table_name,
                              name='0001_initial'):
    from south.migration import Migrations
    import types

    migration = Migrations(app_name)[name]

    def skip_if_table_exists(original):
        def wrapped(self):
            # TODO: look into why we're having to return some ridiculous
            # lambda
            if table_exists(table_name):
                return lambda x=None: None
            return original()
        wrapped.__name__ = original.__name__
        return wrapped

    migration.forwards = types.MethodType(
        skip_if_table_exists(migration.forwards), migration)
Exemplo n.º 18
0
    def _pick_migration(self, migration_name):
        """
        This method will pick a migration object from the catalogue app
        """
        migrations = Migrations('platform')
        for migration in migrations:
            if migration.full_name().split('.')[-1] == migration_name:
                return migration

        return None
Exemplo n.º 19
0
def makemigrations(application,
                   merge=False,
                   dry_run=False,
                   empty=False,
                   extra_applications=None):
    """
    Generate migrations (for both south and django 1.7+)
    """
    from django.core.exceptions import DjangoRuntimeWarning, ImproperlyConfigured
    from django.core.management import call_command

    apps = [application]
    if extra_applications:
        apps += extra_applications

    if DJANGO_1_6:
        from south.exceptions import NoMigrations
        from south.migration import Migrations

        if merge:
            raise DjangoRuntimeWarning(
                u'Option not implemented for Django 1.6 and below')
        for app in apps:
            try:
                if not Migrations(app):
                    raise NoMigrations(app)
            except NoMigrations:
                print('ATTENTION: No migrations found for {0}, '
                      'creating initial migrations.'.format(app))
                try:
                    call_command('schemamigration',
                                 *(app, ),
                                 initial=True,
                                 empty=empty)
                except SystemExit:
                    pass
            except ImproperlyConfigured:
                print('WARNING: The app: {0} could not be found.'.format(app))
            else:
                try:
                    call_command('schemamigration',
                                 *(app, ),
                                 auto=True,
                                 empty=empty)
                except SystemExit:
                    pass
    else:
        for app in apps:
            call_command('makemigrations',
                         *(app, ),
                         merge=merge,
                         dry_run=dry_run,
                         empty=empty)
    def setUp(self):
        super(MigrationTest, self).setUp()

        self.before_migrations = []
        for app_name, version in self.before:
            migrations = Migrations(app_name)
            self.before_migrations.append((app_name, migrations.guess_migration(
                self._get_migration_number(version)).name()))
        self.after_migrations = []
        for app_name, version in self.after:
            migrations = Migrations(app_name)
            self.after_migrations.append((app_name, migrations.guess_migration(
                self._get_migration_number(version)).name()))

        self.before_orm = {}
        for app_name, version in self.before_migrations:
            migrations = Migrations(app_name)
            self.before_orm[app_name] = migrations[version].orm()
        self.after_orm = {}
        for app_name, version in self.after_migrations:
            migrations = Migrations(app_name)
            self.after_orm[app_name] = migrations[version].orm()

        for app_name, version in self.before_migrations:
            # Do a fake migration first to update the migration history.
            self.migrate(app_name, version=None, fake=True)
            self.migrate(app_name, version=version)
    def setUp(self):
        super(SouthMigrationTestCase, self).setUp()
        migrations = Migrations(self.django_application)
        self.start_orm = migrations[self.start_migration].orm()
        self.dest_orm = migrations[self.dest_migration].orm()

        # Ensure the migration history is up-to-date with a fake migration.
        # The other option would be to use the south setting for these tests
        # so that the migrations are used to setup the test db.
        call_command('migrate', self.django_application, fake=True,
                     verbosity=0)
        # Then migrate back to the start migration.
        call_command('migrate', self.django_application, self.start_migration,
                     verbosity=0)
Exemplo n.º 22
0
    def handle(self, app_name=None, **options):
        self.options = options

        if app_name is None:
            print('No app_label given')
            return

        migrations = Migrations(app_name)
        rebase_plan = self.split_migrations(migrations)
        if not rebase_plan.migrations:
            print('No migrations to rebase')
            return

        diffs = []
        for plan_elem in rebase_plan.migrations:
            """Prepare diffs"""
            diffs.append(
                self.diff_frozen_models(plan_elem['previous'],
                                        plan_elem['migration']))

        prev_migration = rebase_plan.onto
        self.prepare_file_cache()
        for diff, migration in zip(diffs, (m['migration']
                                           for m in rebase_plan.migrations)):
            """Rebase - rename migrations and apply diffs"""
            # Prepare new name for migration
            last_migration_no, _ = split_migration_name(prev_migration.name())
            _, migration_base_name = split_migration_name(migration.name())

            migration_path = self.find_migration_path(migration)
            migration_dir = os.path.dirname(migration_path)

            new_migration_filename = '%04i_%s.py' % (last_migration_no + 1,
                                                     migration_base_name)
            new_migration_path = os.path.join(migration_dir,
                                              new_migration_filename)

            # patch migration tree
            new_migration_tree = self.get_updated_migration(migration,
                                                            prev_migration,
                                                            diff=diff)

            self.write_file(new_migration_path,
                            unicode(new_migration_tree).encode('utf-8'))
            self.remove_file(migration_path)

            prev_migration = migration

        self.flush_file_cache()
Exemplo n.º 23
0
 def handle(self, **options):
     
     # Resolve dependencies
     Migrations.calculate_dependencies()
     
     print "digraph G {"
     
     # Print each app in a cluster
     #for migrations in all_migrations():
     #    print "  subgraph %s {" % migrations.app_label()
     #    # Nodes inside here are linked
     #    print (" -> ".join(['"%s.%s"' % (migration.app_label(), migration.name()) for migration in migrations])) + ";"
     #    print "  }"
 
     # For every migration, print its links.
     for migrations in all_migrations():
         for migration in migrations:
             for other in migration.dependencies:
                 print '"%s.%s" -> "%s.%s"' % (
                     other.app_label(), other.name(),
                     migration.app_label(), migration.name(),
                 )
         
     print "}";
Exemplo n.º 24
0
    def handle(self, app=None, name="", freeze_list=None, stdout=False, verbosity=1, **options):
        
        # Any supposed lists that are None become empty lists
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"
        
        # if not name, there's an error
        if not name:
            self.error("You must provide a name for this migration\n" + self.usage_str)
        
        if not app:
            self.error("You must provide an app to create a migration for.\n" + self.usage_str)
        
        # Get the Migrations for this app (creating the migrations dir if needed)
        try:
            migrations = Migrations(app)
        except NoMigrations:
            Migrations.create_migrations_directory(app, verbose=verbosity > 0)
            migrations = Migrations(app)
        
        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)
        
        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)
        
        # So, what's in this file, then?
        file_contents = MIGRATION_TEMPLATE % {
            "frozen_models":  freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps": apps_to_freeze and "complete_apps = [%s]" % (", ".join(map(repr, apps_to_freeze))) or ""
        }
        
        # - is a special name which means 'print to stdout'
        if name == "-":
            print file_contents
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename), "w")
            fp.write(file_contents)
            fp.close()
            print >>sys.stderr, "Created %s." % new_filename
Exemplo n.º 25
0
def _check_migrations_applied():
    """Checks that all south migrations have been applied.
    """
    APP_NAME = 'main'
    all_migrations = Migrations(APP_NAME)
    applied_migrations = [
        migration.get_migration()
        for migration in MigrationHistory.objects.filter(app_name=APP_NAME)
    ]
    not_applied = set(all_migrations) - set(applied_migrations)
    if len(not_applied):
        raise AssertionError("Database migration required. "
                             "Please run `./manage.py migrate main`.\n"
                             "Applied: {applied}\n"
                             "Missing: {not_applied}\n".format(
                                 applied=applied_migrations,
                                 not_applied=not_applied))
Exemplo n.º 26
0
    def handle(self, check_app_name=None, **options):
        runner = simple.DjangoTestSuiteRunner(verbosity=0)
        err_msg = "Failed to migrate %s; see output for hints at missing dependencies:\n"
        hacks.patch_flush_during_test_db_creation()
        failures = 0
        if check_app_name is None:
            app_names = settings.INSTALLED_APPS
        else:
            app_names = [check_app_name]
        for app_name in app_names:
            app_label = app_name.split(".")[-1]
            if app_name == 'south':
                continue

            try:
                Migrations(app_name)
            except (NoMigrations, ImproperlyConfigured):
                continue
            app = loading.get_app(app_label)

            verbosity = int(options.get('verbosity', 1))
            if verbosity >= 1:
                self.stderr.write("processing %s\n" % app_name)

            old_config = runner.setup_databases()
            try:
                call_command('migrate',
                             app_label,
                             noinput=True,
                             verbosity=verbosity)
                for model in loading.get_models(app):
                    dummy = model._default_manager.exists()
            except (KeyboardInterrupt, SystemExit):
                raise
            except Exception as e:
                failures += 1
                if verbosity >= 1:
                    self.stderr.write(err_msg % app_name)
                    self.stderr.write("%s\n" % e)
            finally:
                runner.teardown_databases(old_config)
        if failures > 0:
            raise CommandError("Missing depends_on found in %s app(s)." %
                               failures)
        self.stderr.write("No missing depends_on found.\n")
 def handle(self, *args, **options):
     global command_log
     global unchanged_count
     unchanged_count = 0
     ok_to_migrate = True
     force = options.pop('force', False)
     dry_run = options.pop('dry_run', False)
     verbosity = int(options.get('verbosity', 1))
     
     # Workaround South's sneaky method of ending commands with error() calls
     SchemaMigration.error = error_log
     # Get list of apps that have models which subclass FeinCMSDocument
     apps_to_migrate = [model._meta.app_label for model in get_subclasses(FeinCMSDocument)]
     if verbosity:
         print 'Automatic schema migrations will be created for the following apps:'
         print '\t%s' % ', '.join(apps_to_migrate)
     # Exit if running a dry run
     if dry_run:
         return
     # First check if the apps already have migrations
     for app in apps_to_migrate:
         try:
             existing_migrations = Migrations(app, force_creation=False, verbose_creation=False)
             if not existing_migrations:
                 raise NoMigrations(app)
         except NoMigrations:
             if not force:
                 print 'The app "%s" is not tracked by South, either create an initial migration or run this command with "--force" to do so automatically.' % app
                 ok_to_migrate = False
     # Now migrate the apps
     if ok_to_migrate:
         for app in apps_to_migrate:
             try:
                 SchemaMigration().handle(app, auto=True, interactive=False, **options)
             except ExitCommand:
                 pass
         if verbosity > 1:
             print 'Done. The output from the commands was:\n\t',
             print '\n\t'.join(command_log)
         elif verbosity:
             if unchanged_count == len(apps_to_migrate):
                 print 'No changes detected in any of the above apps.'
             else:
                 print 'Finished creating migrations.'
Exemplo n.º 28
0
def skip_initial_migration_if_applied(settings, app_name, table_name):
    from south.migration import Migrations
    import types

    migrations = Migrations(app_name)
    # fix the initial migration
    initial = migrations['0001_initial']

    def initial_forwards(original):
        def wrapped(self):
            # TODO: look into why we're having to return some ridiculous
            # lambda
            if table_exists(table_name):
                return lambda x=None: None
            return original()

        wrapped.__name__ = original.__name__
        return wrapped

    initial.forwards = types.MethodType(initial_forwards(initial.forwards),
                                        initial)
Exemplo n.º 29
0
                else:
                    schema_cmd.handle(  #pylint:disable=no-member
                        app, initial=True)
                    initial_apps += [app]
            else:
                print("warning: App %s does not seem to contain any Model" %
                      app)
        except OSError, err:
            print "error: App %s, %s" % (app, err)
        except RuntimeError, err:
            print "warning: App %s, %s" % (app, err)
        except ImproperlyConfigured:
            print "warning: App %s does not seem to contain a models.py" % app

    # Clear the cached Migrations instances now that we have more of them.
    Migrations._clear_cache()  #pylint: disable=no-member,protected-access
    migrate_cmd = migrate.Command()
    for app in initial_apps:
        print "initial migrate for %s" % app
        migrate_cmd.handle(app, fake=True)
    print "MIGRATE ALL!"
    migrate_cmd.handle(no_initial_data=True)
    return 0


def migrate_all():
    """
    Create schema migrations for all apps specified in INSTALLED_APPS,
    then run a migrate command.
    """
    if 'south' in settings.INSTALLED_APPS:
Exemplo n.º 30
0
class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--all',
                    action='store_true',
                    dest='all_apps',
                    default=False,
                    help='Run the specified migration for all apps.'),
        make_option(
            '--list',
            action='store_true',
            dest='show_list',
            default=False,
            help='List migrations noting those that have been applied'),
        make_option('--changes',
                    action='store_true',
                    dest='show_changes',
                    default=False,
                    help='List changes for migrations'),
        make_option('--skip',
                    action='store_true',
                    dest='skip',
                    default=False,
                    help='Will skip over out-of-order missing migrations'),
        make_option(
            '--merge',
            action='store_true',
            dest='merge',
            default=False,
            help=
            'Will run out-of-order missing migrations as they are - no rollbacks.'
        ),
        make_option('--no-initial-data',
                    action='store_true',
                    dest='no_initial_data',
                    default=False,
                    help='Skips loading initial data if specified.'),
        make_option(
            '--fake',
            action='store_true',
            dest='fake',
            default=False,
            help=
            "Pretends to do the migrations, but doesn't actually execute them."
        ),
        make_option(
            '--db-dry-run',
            action='store_true',
            dest='db_dry_run',
            default=False,
            help=
            "Doesn't execute the SQL generated by the db methods, and doesn't store a record that the migration(s) occurred. Useful to test migrations before applying them."
        ),
        make_option(
            '--delete-ghost-migrations',
            action='store_true',
            dest='delete_ghosts',
            default=False,
            help=
            "Tells South to delete any 'ghost' migrations (ones in the database but not on disk)."
        ),
        make_option(
            '--ignore-ghost-migrations',
            action='store_true',
            dest='ignore_ghosts',
            default=False,
            help=
            "Tells South to ignore any 'ghost' migrations (ones in the database but not on disk) and continue to apply new migrations."
        ),
        make_option(
            '--noinput',
            action='store_false',
            dest='interactive',
            default=True,
            help='Tells Django to NOT prompt the user for input of any kind.'),
        make_option('--database',
                    action='store',
                    dest='database',
                    default=DEFAULT_DB_ALIAS,
                    help='Nominates a database to synchronize. '
                    'Defaults to the "default" database.'),
    )
    if '--verbosity' not in [
            opt.get_opt_string() for opt in BaseCommand.option_list
    ]:
        option_list += (make_option(
            '--verbosity',
            action='store',
            dest='verbosity',
            default='1',
            type='choice',
            choices=['0', '1', '2'],
            help=
            'Verbosity level; 0=minimal output, 1=normal output, 2=all output'
        ), )
    help = "Runs migrations for all apps."
    args = "[appname] [migrationname|zero] [--all] [--list] [--skip] [--merge] [--no-initial-data] [--fake] [--db-dry-run] [--database=dbalias]"

    def handle(self,
               app=None,
               target=None,
               skip=False,
               merge=False,
               backwards=False,
               fake=False,
               db_dry_run=False,
               show_list=False,
               show_changes=False,
               database=DEFAULT_DB_ALIAS,
               delete_ghosts=False,
               ignore_ghosts=False,
               **options):

        # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb
        # This code imports any module named 'management' in INSTALLED_APPS.
        # The 'management' module is the preferred way of listening to post_syncdb
        # signals, and since we're sending those out with create_table migrations,
        # we need apps to behave correctly.
        for app_name in settings.INSTALLED_APPS:
            try:
                __import__(app_name + '.management', {}, {}, [''])
            except ImportError, exc:
                msg = exc.args[0]
                if not msg.startswith(
                        'No module named') or 'management' not in msg:
                    raise
        # END DJANGO DUPE CODE

        # if all_apps flag is set, shift app over to target
        if options.get('all_apps', False):
            target = app
            app = None

        # Migrate each app
        if app:
            try:
                apps = [Migrations(app)]
            except NoMigrations:
                print "The app '%s' does not appear to use migrations." % app
                print "./manage.py migrate " + self.args
                return
        else:
            apps = list(migration.all_migrations())

        # Do we need to show the list of migrations?
        if show_list and apps:
            list_migrations(apps, database)

        if show_changes and apps:
            show_migration_changes(apps)

        if not (show_list or show_changes):

            for app in apps:
                result = migration.migrate_app(
                    app,
                    target_name=target,
                    fake=fake,
                    db_dry_run=db_dry_run,
                    verbosity=int(options.get('verbosity', 0)),
                    interactive=options.get('interactive', True),
                    load_initial_data=not options.get('no_initial_data',
                                                      False),
                    merge=merge,
                    skip=skip,
                    database=database,
                    delete_ghosts=delete_ghosts,
                    ignore_ghosts=ignore_ghosts,
                )
                if result is False:
                    sys.exit(1)  # Migration failed, so the command fails.
Exemplo n.º 31
0
    def handle(self,
               app=None,
               target=None,
               skip=False,
               merge=False,
               backwards=False,
               fake=False,
               db_dry_run=False,
               show_list=False,
               show_changes=False,
               database=DEFAULT_DB_ALIAS,
               delete_ghosts=False,
               ignore_ghosts=False,
               **options):

        # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb
        # This code imports any module named 'management' in INSTALLED_APPS.
        # The 'management' module is the preferred way of listening to post_syncdb
        # signals, and since we're sending those out with create_table migrations,
        # we need apps to behave correctly.
        for app_name in settings.INSTALLED_APPS:
            try:
                import_module('.management', app_name)
            except ImportError as exc:
                msg = exc.args[0]
                if not msg.startswith(
                        'No module named') or 'management' not in msg:
                    raise
        # END DJANGO DUPE CODE

        # if all_apps flag is set, shift app over to target
        if options.get('all_apps', False):
            target = app
            app = None

        # Migrate each app
        if app:
            try:
                apps = [Migrations(app)]
            except NoMigrations:
                print("The app '%s' does not appear to use migrations." % app)
                print("./manage.py migrate " + self.args)
                return
        else:
            apps = list(migration.all_migrations())

        # Do we need to show the list of migrations?
        if show_list and apps:
            list_migrations(apps, database, **options)

        if show_changes and apps:
            show_migration_changes(apps)

        if not (show_list or show_changes):

            for app in apps:
                result = migration.migrate_app(
                    app,
                    target_name=target,
                    fake=fake,
                    db_dry_run=db_dry_run,
                    verbosity=int(options.get('verbosity', 0)),
                    interactive=options.get('interactive', True),
                    load_initial_data=not options.get('no_initial_data',
                                                      False),
                    merge=merge,
                    skip=skip,
                    database=database,
                    delete_ghosts=delete_ghosts,
                    ignore_ghosts=ignore_ghosts,
                )
                if result is False:
                    sys.exit(1)  # Migration failed, so the command fails.
Exemplo n.º 32
0
    def handle(self, *args, **options):

        _auto = options.get('auto', False)
        # Loop through all give apps
        # Or fail as no apps are supplied.
        if len(args) <= 0:
            self.say("No apps supplied")
            exit(1)

        for a in args:
            try:
                module, app = self.app_label_to_app_module(a)

                #print "Objects", module, app
            except ImproperlyConfigured as (e):
                module, app = None, None
                self.say("App '%s' could not be found." % a)

            if app:
                me = self.migrations_exist(module)
                if me:
                    self.say("Auto migrations for %s" % a)
                    _auto = True
                else:
                    self.say("New migrations for %s" % a)
                    _auto = False

                if _auto == True:
                    _initial = False
                else:
                    _initial = True
                from django.core import management

                options.update({'initial': _initial, 'auto': _auto})
                p = str(a)

                try:
                    management.call_command('schemamigration', p, **options)
                finally:
                    from south.migration import Migration, Migrations
                    # Migrate each app

                    if a:
                        try:

                            apps = [Migrations(a)]
                            _s = 's'
                            if len(apps) == 1: _s = ''
                            print "Migrating %s app%s in '%s' " % (len(apps),
                                                                   _s, a)

                            for app in apps:
                                result = migration.migrate_app(
                                    apps,
                                    target_name=None,
                                    fake=options.get('fake', False),
                                    db_dry_run=options.get(
                                        'db_dry_run', False),
                                    verbosity=int(options.get('verbosity', 0)),
                                    interactive=options.get(
                                        'interactive', True),
                                    load_initial_data=not options.get(
                                        'no_initial_data', False),
                                    merge=options.get('merge', True),
                                    skip=False,
                                    database=options.get(
                                        'database', DEFAULT_DB_ALIAS),
                                    delete_ghosts=options.get(
                                        'delete_ghosts', False),
                                    ignore_ghosts=options.get(
                                        'ignore_ghosts', False),
                                )
                            if result is False:
                                sys.exit(
                                    1
                                )  # Migration failed, so the command fails.
                        except NoMigrations:
                            print "The app '%s' does not appear to use migrations." % app
                            print "./manage.py migrate " + self.args
                            return
                    else:
                        apps = list(migration.all_migrations())
Exemplo n.º 33
0
    def handle(self,
               app=None,
               name="",
               added_model_list=None,
               added_field_list=None,
               freeze_list=None,
               initial=False,
               auto=False,
               stdout=False,
               added_index_list=None,
               verbosity=1,
               empty=False,
               update=False,
               **options):

        # Any supposed lists that are None become empty lists
        added_model_list = added_model_list or []
        added_field_list = added_field_list or []
        added_index_list = added_index_list or []
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"

        # Only allow valid names
        if re.search('[^_\w]', name) and name != "-":
            self.error(
                "Migration names should contain only alphanumeric characters and underscores."
            )

        # Make sure options are compatable
        if initial and (added_model_list or added_field_list or auto):
            self.error(
                "You cannot use --initial and other options together\n" +
                self.usage_str)

        if auto and (added_model_list or added_field_list or initial):
            self.error("You cannot use --auto and other options together\n" +
                       self.usage_str)

        if not app:
            self.error("You must provide an app to create a migration for.\n" +
                       self.usage_str)

        # See if the app exists
        app = app.split(".")[-1]
        try:
            app_module = models.get_app(app)
        except ImproperlyConfigured:
            print("There is no enabled application matching '%s'." % app)
            return

        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app,
                                force_creation=True,
                                verbose_creation=int(verbosity) > 0)

        # What actions do we need to do?
        if auto:
            # Get the old migration
            try:
                last_migration = migrations[-2 if update else -1]
            except IndexError:
                self.error(
                    "You cannot use --auto on an app with no migrations. Try --initial."
                )
            # Make sure it has stored models
            if migrations.app_label() not in getattr(
                    last_migration.migration_class(), "complete_apps", []):
                self.error(
                    "You cannot use automatic detection, 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,
            )

        elif initial:
            # Do an initial migration
            change_source = changes.InitialChanges(migrations)

        else:
            # Read the commands manually off of the arguments
            if (added_model_list or added_field_list or added_index_list):
                change_source = changes.ManualChanges(
                    migrations,
                    added_model_list,
                    added_field_list,
                    added_index_list,
                )
            elif empty:
                change_source = None
            else:
                print(
                    "You have not passed any of --initial, --auto, --empty, --add-model, --add-field or --add-index.",
                    file=sys.stderr)
                sys.exit(1)

        # Validate this so we can access the last migration without worrying
        if update and not migrations:
            self.error("You cannot use --update on an app with no migrations.")

        # if not name, there's an error
        if not name:
            if change_source:
                name = change_source.suggest_name()
            if update:
                name = re.sub(r'^\d{4}_', '', migrations[-1].name())
            if not name:
                self.error("You must provide a name for this migration\n" +
                           self.usage_str)

        # Get the actions, and then insert them into the actions lists
        forwards_actions = []
        backwards_actions = []
        if change_source:
            for action_name, params in change_source.get_changes():
                # Run the correct Action class
                try:
                    action_class = getattr(actions, action_name)
                except AttributeError:
                    raise ValueError("Invalid action name from source: %s" %
                                     action_name)
                else:
                    action = action_class(**params)
                    action.add_forwards(forwards_actions)
                    action.add_backwards(backwards_actions)
                    print(action.console_line(), file=sys.stderr)

        # Nowt happen? That's not good for --auto.
        if auto and not forwards_actions:
            self.error("Nothing seems to have changed.")

        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)

        # So, what's in this file, then?
        file_contents = self.get_migration_template() % {
            "forwards":
            "\n".join(forwards_actions or ["        pass"]),
            "backwards":
            "\n".join(backwards_actions or ["        pass"]),
            "frozen_models":
            freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps":
            apps_to_freeze and "complete_apps = [%s]" %
            (", ".join(map(repr, apps_to_freeze))) or ""
        }

        # Deal with update mode as late as possible, avoid a rollback as long
        # as something else can go wrong.
        if update:
            last_migration = migrations[-1]
            if MigrationHistory.objects.filter(
                    applied__isnull=False,
                    app_name=app,
                    migration=last_migration.name()):
                print(
                    "Migration to be updated, %s, is already applied, rolling it back now..."
                    % last_migration.name(),
                    file=sys.stderr)
                migrate_app(migrations, 'current-1', verbosity=verbosity)
            for ext in ('py', 'pyc'):
                old_filename = "%s.%s" % (os.path.join(
                    migrations.migrations_dir(), last_migration.filename), ext)
                if os.path.isfile(old_filename):
                    os.unlink(old_filename)
            migrations.remove(last_migration)

        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)

        # - is a special name which means 'print to stdout'
        if name == "-":
            print(file_contents)
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename),
                      "w")
            fp.write(file_contents)
            fp.close()
            verb = 'Updated' if update else 'Created'
            if empty:
                print(
                    "%s %s. You must now edit this migration and add the code for each direction."
                    % (verb, new_filename),
                    file=sys.stderr)
            else:
                print(
                    "%s %s. You can now apply this migration with: ./manage.py migrate %s"
                    % (verb, new_filename, app),
                    file=sys.stderr)
Exemplo n.º 34
0
    def handle(self, app=None, name="", added_model_list=None, added_field_list=None, freeze_list=None, initial=False, auto=False, stdout=False, added_index_list=None, verbosity=1, **options):
        
        # Any supposed lists that are None become empty lists
        added_model_list = added_model_list or []
        added_field_list = added_field_list or []
        added_index_list = added_index_list or []
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"
        
        # Make sure options are compatable
        if initial and (added_model_list or added_field_list or auto):
            self.error("You cannot use --initial and other options together\n" + self.usage_str)
        
        if auto and (added_model_list or added_field_list or initial):
            self.error("You cannot use --auto and other options together\n" + self.usage_str)
        
        # specify the default name 'initial' if a name wasn't specified and we're
        # doing a migration for an entire app
        if not name and initial:
            name = 'initial'
        
        # if not name, there's an error
        if not name:
            self.error("You must provide a name for this migration\n" + self.usage_str)
        
        if not app:
            self.error("You must provide an app to create a migration for.\n" + self.usage_str)
        
        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app, force_creation=True, verbose_creation=verbosity > 0)
        
        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)
        
        # What actions do we need to do?
        if auto:
            # Get the old migration
            try:
                last_migration = migrations[-1]
            except IndexError:
                self.error("You cannot use --auto on an app with no migrations. Try --initial.")
            # Make sure it has stored models
            if migrations.app_label() not in getattr(last_migration.migration_class(), "complete_apps", []):
                self.error("You cannot use automatic detection, 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,
            )
        
        elif initial:
            # Do an initial migration
            change_source = changes.InitialChanges(migrations)
        
        else:
            # Read the commands manually off of the arguments
            if (added_model_list or added_field_list or added_index_list):
                change_source = changes.ManualChanges(
                    migrations,
                    added_model_list,
                    added_field_list,
                    added_index_list,
                )
            else:
                print >>sys.stderr, "You have not passed any of --initial, --auto, --add-model, --add-field or --add-index."
                sys.exit(1)
        
        # Get the actions, and then insert them into the actions lists
        forwards_actions = []
        backwards_actions = []
        for action_name, params in change_source.get_changes():
            # Run the correct Action class
            try:
                action_class = getattr(actions, action_name)
            except AttributeError:
                raise ValueError("Invalid action name from source: %s" % action_name)
            else:
                action = action_class(**params)
                action.add_forwards(forwards_actions)
                action.add_backwards(backwards_actions)
                print >>sys.stderr, action.console_line()
        
        # Nowt happen? That's not good for --auto.
        if auto and not forwards_actions:
            self.error("Nothing seems to have changed.")
        
        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)
        
        # So, what's in this file, then?
        file_contents = MIGRATION_TEMPLATE % {
            "forwards": "\n".join(forwards_actions), 
            "backwards": "\n".join(backwards_actions), 
            "frozen_models":  freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps": apps_to_freeze and "complete_apps = [%s]" % (", ".join(map(repr, apps_to_freeze))) or ""
        }
        
        # - is a special name which means 'print to stdout'
        if name == "-":
            print file_contents
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename), "w")
            fp.write(file_contents)
            fp.close()
            print >>sys.stderr, "Created %s. You can now apply this migration with: ./manage.py migrate %s" % (new_filename, app)
Exemplo n.º 35
0
                else:
                    schema_cmd.handle( #pylint:disable=no-member
                        app, initial=True)
                    initial_apps += [app]
            else:
                print("warning: App %s does not seem to contain any Model" %
                    app)
        except OSError, err:
            print "error: App %s, %s" % (app, err)
        except RuntimeError, err:
            print "warning: App %s, %s" % (app, err)
        except ImproperlyConfigured:
            print "warning: App %s does not seem to contain a models.py" % app

    # Clear the cached Migrations instances now that we have more of them.
    Migrations._clear_cache() #pylint: disable=no-member,protected-access
    migrate_cmd = migrate.Command()
    for app in initial_apps:
        print "initial migrate for %s" % app
        migrate_cmd.handle(app, fake=True)
    print "MIGRATE ALL!"
    migrate_cmd.handle(no_initial_data=True)
    return 0


def migrate_all():
    """
    Create schema migrations for all apps specified in INSTALLED_APPS,
    then run a migrate command.
    """
    if 'south' in settings.INSTALLED_APPS:
Exemplo n.º 36
0
 def migrate(self, target):
     """ Migrate and return target orm handler. """
     call_command('migrate', self.app, target, verbosity=0)
     return Migrations(self.app).guess_migration(target).orm()
Exemplo n.º 37
0
    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)))
Exemplo n.º 38
0
class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--all',
                    action='store_true',
                    dest='all_apps',
                    default=False,
                    help='Run the specified migration for all apps.'),
        make_option(
            '--list',
            action='store_true',
            dest='show_list',
            default=False,
            help='List migrations noting those that have been applied'),
        make_option('--changes',
                    action='store_true',
                    dest='show_changes',
                    default=False,
                    help='List changes for migrations'),
        make_option('--skip',
                    action='store_true',
                    dest='skip',
                    default=False,
                    help='Will skip over out-of-order missing migrations'),
        make_option(
            '--merge',
            action='store_true',
            dest='merge',
            default=False,
            help=
            'Will run out-of-order missing migrations as they are - no rollbacks.'
        ),
        make_option('--no-initial-data',
                    action='store_true',
                    dest='no_initial_data',
                    default=False,
                    help='Skips loading initial data if specified.'),
        make_option(
            '--fake',
            action='store_true',
            dest='fake',
            default=False,
            help=
            "Pretends to do the migrations, but doesn't actually execute them."
        ),
        make_option(
            '--db-dry-run',
            action='store_true',
            dest='db_dry_run',
            default=False,
            help=
            "Doesn't execute the SQL generated by the db methods, and doesn't store a record that the migration(s) occurred. Useful to test migrations before applying them."
        ),
        make_option(
            '--delete-ghost-migrations',
            action='store_true',
            dest='delete_ghosts',
            default=False,
            help=
            "Tells South to delete any 'ghost' migrations (ones in the database but not on disk)."
        ),
        make_option(
            '--ignore-ghost-migrations',
            action='store_true',
            dest='ignore_ghosts',
            default=False,
            help=
            "Tells South to ignore any 'ghost' migrations (ones in the database but not on disk) and continue to apply new migrations."
        ),
        make_option(
            '--noinput',
            action='store_false',
            dest='interactive',
            default=True,
            help='Tells Django to NOT prompt the user for input of any kind.'),
        make_option('--database',
                    action='store',
                    dest='database',
                    default=DEFAULT_DB_ALIAS,
                    help='Nominates a database to synchronize. '
                    'Defaults to the "default" database.'),
        make_option(
            '--hack',  # KA-LITE-MOD: needed for relaunch_external hack
            action="store_true",
            dest="hack",
            default=False,
            help="Flag that we're getting an external callback ",
        ),
    )
    if '--verbosity' not in [
            opt.get_opt_string() for opt in BaseCommand.option_list
    ]:
        option_list += (make_option(
            '--verbosity',
            action='store',
            dest='verbosity',
            default='1',
            type='choice',
            choices=['0', '1', '2'],
            help=
            'Verbosity level; 0=minimal output, 1=normal output, 2=all output'
        ), )
    help = "Runs migrations for all apps."
    args = "[appname] [migrationname|zero] [--all] [--list] [--skip] [--merge] [--no-initial-data] [--fake] [--db-dry-run] [--database=dbalias]"

    def relaunch_external(self):
        """
        This is a KA Lite hack. #KA-LITE-MOD

        In our git-based update command (until version 0.10.3), we update the code, then run
        run the 'migrate' command under the old code (since it's loaded into memory).
        This can cause conflicting / now-outdated imports.

        The right thing to do is to run migrate via subprocess, so that it runs all fresh, new code.
        Alas, we've shipped versions that don't do this already, so we can't go back and fix.

        The hack here is: detect when this is happening, then force migrate to re-launch itself via subprocess.

        Note that this only works if this file (migrate.py) hasn't already been loaded into the process.  It
        shouldn't be... but it's worth keeping in mind!
        """
        import sys
        import settings
        import utils.django_utils.command
        reload(
            utils.django_utils.command
        )  # this is necessary because the 0.10.2 version of this code has a bug!

        # Launch through subprocess, then print output.
        sys.stdout.write(
            "[NOTE version upgrade hack: running 'migrate' through subprocess.]\n\n"
        )
        sys.stdout.write(
            "Please wait. DO NOT CANCEL WHILE MIGRATE RUNS, EVEN THOUGH YOU'RE RECEIVING NO OUTPUT!!  JUST WAIT!!\n"
        )
        sys.stdout.write(
            "Output will print below when migrate is complete.\n\n")

        (out, err,
         rc) = utils.django_utils.command.call_outside_command_with_output(
             "migrate",
             merge=True,
             hack=True,
             manage_py_dir=settings.PROJECT_PATH)
        sys.stdout.write(out)
        if rc:
            sys.stderr.write(err)
        sys.exit(0)  # abort the rest of the migrate / update command

    def handle(self,
               app=None,
               target=None,
               skip=False,
               merge=False,
               backwards=False,
               fake=False,
               db_dry_run=False,
               show_list=False,
               show_changes=False,
               database=DEFAULT_DB_ALIAS,
               delete_ghosts=False,
               ignore_ghosts=False,
               **options):

        if "update" in sys.argv and "--hack" not in sys.argv:
            self.relaunch_external()

        # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb
        # This code imports any module named 'management' in INSTALLED_APPS.
        # The 'management' module is the preferred way of listening to post_syncdb
        # signals, and since we're sending those out with create_table migrations,
        # we need apps to behave correctly.
        for app_name in settings.INSTALLED_APPS:
            try:
                import_module('.management', app_name)
            except ImportError, exc:
                msg = exc.args[0]
                if not msg.startswith(
                        'No module named') or 'management' not in msg:
                    raise
        # END DJANGO DUPE CODE

        # if all_apps flag is set, shift app over to target
        if options.get('all_apps', False):
            target = app
            app = None

        # Migrate each app
        if app:
            try:
                apps = [Migrations(app)]
            except NoMigrations:
                print "The app '%s' does not appear to use migrations." % app
                print "./manage.py migrate " + self.args
                return
        else:
            apps = list(migration.all_migrations())

        # Do we need to show the list of migrations?
        if show_list and apps:
            list_migrations(apps, database, **options)

        if show_changes and apps:
            show_migration_changes(apps)

        if not (show_list or show_changes):

            for app in apps:
                result = migration.migrate_app(
                    app,
                    target_name=target,
                    fake=fake,
                    db_dry_run=db_dry_run,
                    verbosity=int(options.get('verbosity', 0)),
                    interactive=options.get('interactive', True),
                    load_initial_data=not options.get('no_initial_data',
                                                      False),
                    merge=merge,
                    skip=skip,
                    database=database,
                    delete_ghosts=delete_ghosts,
                    ignore_ghosts=ignore_ghosts,
                )
                if result is False:
                    sys.exit(1)  # Migration failed, so the command fails.
Exemplo n.º 39
0
    def handle(self,
               app=None,
               name="",
               added_model_list=None,
               added_field_list=None,
               freeze_list=None,
               initial=False,
               auto=False,
               stdout=False,
               added_index_list=None,
               verbosity=1,
               empty=False,
               **options):

        # Any supposed lists that are None become empty lists
        added_model_list = added_model_list or []
        added_field_list = added_field_list or []
        added_index_list = added_index_list or []
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"

        # Only allow valid names
        if re.search('[^_\w]', name) and name != "-":
            self.error(
                "Migration names should contain only alphanumeric characters and underscores."
            )

        # Make sure options are compatable
        if initial and (added_model_list or added_field_list or auto):
            self.error(
                "You cannot use --initial and other options together\n" +
                self.usage_str)

        if auto and (added_model_list or added_field_list or initial):
            self.error("You cannot use --auto and other options together\n" +
                       self.usage_str)

        if not app:
            self.error("You must provide an app to create a migration for.\n" +
                       self.usage_str)

        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app,
                                force_creation=True,
                                verbose_creation=verbosity > 0)

        # What actions do we need to do?
        if auto:
            # Get the old migration
            try:
                last_migration = migrations[-1]
            except IndexError:
                self.error(
                    "You cannot use --auto on an app with no migrations. Try --initial."
                )
            # Make sure it has stored models
            if migrations.app_label() not in getattr(
                    last_migration.migration_class(), "complete_apps", []):
                self.error(
                    "You cannot use automatic detection, 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,
            )

        elif initial:
            # Do an initial migration
            change_source = changes.InitialChanges(migrations)

        else:
            # Read the commands manually off of the arguments
            if (added_model_list or added_field_list or added_index_list):
                change_source = changes.ManualChanges(
                    migrations,
                    added_model_list,
                    added_field_list,
                    added_index_list,
                )
            elif empty:
                change_source = None
            else:
                print >> sys.stderr, "You have not passed any of --initial, --auto, --empty, --add-model, --add-field or --add-index."
                sys.exit(1)

        # if not name, there's an error
        if not name:
            if change_source:
                name = change_source.suggest_name()
            if not name:
                self.error("You must provide a name for this migration\n" +
                           self.usage_str)

        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)

        # Get the actions, and then insert them into the actions lists
        forwards_actions = []
        backwards_actions = []
        if change_source:
            for action_name, params in change_source.get_changes():
                # Run the correct Action class
                try:
                    action_class = getattr(actions, action_name)
                except AttributeError:
                    raise ValueError("Invalid action name from source: %s" %
                                     action_name)
                else:
                    action = action_class(**params)
                    action.add_forwards(forwards_actions)
                    action.add_backwards(backwards_actions)
                    print >> sys.stderr, action.console_line()

        # Nowt happen? That's not good for --auto.
        if auto and not forwards_actions:
            self.error("Nothing seems to have changed.")

        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)

        # So, what's in this file, then?
        file_contents = MIGRATION_TEMPLATE % {
            "forwards":
            "\n".join(forwards_actions or ["pass"]),
            "backwards":
            "\n".join(backwards_actions or ["pass"]),
            "frozen_models":
            freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps":
            apps_to_freeze and "complete_apps = [%s]" %
            (", ".join(map(repr, apps_to_freeze))) or ""
        }

        # - is a special name which means 'print to stdout'
        if name == "-":
            print file_contents
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename),
                      "w")
            fp.write(file_contents)
            fp.close()
            if empty:
                print >> sys.stderr, "Created %s. You must now edit this migration and add the code for each direction." % new_filename
            else:
                print >> sys.stderr, "Created %s. You can now apply this migration with: ./manage.py migrate %s" % (
                    new_filename, app)
Exemplo n.º 40
0
            if (not msg.startswith('No module named')
                    and not msg.endswith(' is unknown')
                ) or 'management' not in msg:
                raise

    # END DJANGO DUPE CODE

    # if all_apps flag is set, shift app over to target
    if options.get('all_apps', False):
        target = app
        app = None

    # Migrate each app
    if app:
        try:
            apps = [Migrations(app)]
        except NoMigrations:
            print "The app '%s' does not appear to use migrations." % app
            print "./manage.py migrate " + self.args
            return
    else:
        apps = list(migration.all_migrations())

    # Do we need to show the list of migrations?
    if show_list and apps:
        list_migrations(apps, database, **options)

    if not show_list:

        for app in apps:
            result = migration.migrate_app(
Exemplo n.º 41
0
def makemigrations(migrate_plugins=True, merge=False, squash=False):
    applications = [
        # core applications
        'cms',
        'menus',
        # testing applications
        'meta',
        'manytomany_rel',
        'fileapp',
        'placeholderapp',
        'sampleapp',
        'fakemlng',
        'one_thing',
        'extensionapp',
        'objectpermissionsapp',
        'bunch_of_plugins',
        'mti_pluginapp',
    ]
    if os.environ.get("AUTH_USER_MODEL") == "emailuserapp.EmailUser":
        applications.append('emailuserapp')
    if migrate_plugins:
        applications.extend([
            # official plugins
            'djangocms_inherit',
            'djangocms_googlemap',
            'djangocms_column',
            'djangocms_style',
            'djangocms_link',
            'djangocms_file',
            'djangocms_text_ckeditor',
            'djangocms_picture',
            'djangocms_teaser',
            'djangocms_file',
            'djangocms_flash',
            'djangocms_video',
        ])
    if DJANGO_1_6:
        from south.exceptions import NoMigrations
        from south.migration import Migrations

        if merge:
            raise DjangoRuntimeWarning(
                u'Option not implemented for Django 1.6')
        for application in applications:
            try:
                Migrations(application)
            except NoMigrations:
                print('ATTENTION: No migrations found for {0}, creating '
                      'initial migrations.'.format(application))
                try:
                    call_command('schemamigration', application, initial=True)
                except SystemExit:
                    pass
            except ImproperlyConfigured:
                print('WARNING: The app: {0} could not be found.'.format(
                    application))
            else:
                try:
                    call_command('schemamigration', application, auto=True)
                except SystemExit:
                    pass
    else:
        call_command('makemigrations', *applications, merge=merge)
Exemplo n.º 42
0
    def handle(self, app=None, name="", added_model_list=None,
               added_field_list=None, freeze_list=None, initial=False,
               auto=False, stdout=False, added_index_list=None, verbosity=1,
               empty=False, update=False, **options):

        # Any supposed lists that are None become empty lists
        added_model_list = added_model_list or []
        added_field_list = added_field_list or []
        added_index_list = added_index_list or []
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"

        # Only allow valid names
        if re.search('[^_\w]', name) and name != "-":
            self.error(
                "Migration names should contain only alphanumeric characters and underscores.")

        # Make sure options are compatable
        if initial and (added_model_list or added_field_list or auto):
            self.error(
                "You cannot use --initial and other options together\n" + self.usage_str)

        if auto and (added_model_list or added_field_list or initial):
            self.error(
                "You cannot use --auto and other options together\n" + self.usage_str)

        if not app:
            self.error(
                "You must provide an app to create a migration for.\n" + self.usage_str)

        # See if the app exists
        app = app.split(".")[-1]
        try:
            app_module = models.get_app(app)
        except ImproperlyConfigured:
            print("There is no enabled application matching '%s'." % app)
            return

        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app, force_creation=True,
                                verbose_creation=int(verbosity) > 0)

        # What actions do we need to do?
        if auto:
            # Get the old migration
            try:
                last_migration = migrations[-2 if update else -1]
            except IndexError:
                self.error(
                    "You cannot use --auto on an app with no migrations. Try --initial.")
            # Make sure it has stored models
            if migrations.app_label() not in getattr(
                    last_migration.migration_class(), "complete_apps", []):
                self.error(
                    "You cannot use automatic detection, 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,
            )

        elif initial:
            # Do an initial migration
            change_source = changes.InitialChanges(migrations)

        else:
            # Read the commands manually off of the arguments
            if (added_model_list or added_field_list or added_index_list):
                change_source = changes.ManualChanges(
                    migrations,
                    added_model_list,
                    added_field_list,
                    added_index_list,
                )
            elif empty:
                change_source = None
            else:
                print(
                    "You have not passed any of --initial, --auto, --empty, --add-model, --add-field or --add-index.",
                    file=sys.stderr)
                sys.exit(1)

        # Validate this so we can access the last migration without worrying
        if update and not migrations:
            self.error("You cannot use --update on an app with no migrations.")

        # if not name, there's an error
        if not name:
            if change_source:
                name = change_source.suggest_name()
            if update:
                name = re.sub(r'^\d{4}_', '', migrations[-1].name())
            if not name:
                self.error(
                    "You must provide a name for this migration\n" + self.usage_str)

        # Get the actions, and then insert them into the actions lists
        forwards_actions = []
        backwards_actions = []

        if change_source:
            for action_name, params in change_source.get_changes():
                # Run the correct Action class
                try:
                    action_class = getattr(actions, action_name)
                except AttributeError:
                    raise ValueError(
                        "Invalid action name from source: %s" % action_name)
                else:
                    action = action_class(**params)
                    action.add_forwards(forwards_actions)
                    action.add_backwards(backwards_actions)
                    print(action.console_line(), file=sys.stderr)

        # Nowt happen? That's not good for --auto.
        if auto and not forwards_actions:
            self.error("Nothing seems to have changed.")

        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)

        # So, what's in this file, then?
        file_contents = MIGRATION_TEMPLATE % {
            "forwards": "\n".join(forwards_actions or ["        pass"]),
            "backwards": "\n".join(backwards_actions or ["        pass"]),
            "frozen_models": freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps": apps_to_freeze and "complete_apps = [%s]" % (
                ", ".join(map(repr, apps_to_freeze))) or ""
        }

        # Custom Bluebottle
        # We find and replace the base apps with our mapped models
        for model in MODEL_MAP:
            model_map = MODEL_MAP[model]
            mapping = {
                'u"orm[\'{0}\']"'.format(model_map[
                                             'model']): '"orm[\'{0}\']".format(MODEL_MAP[\'{1}\'][\'model\'])'.format(
                    '{0}', model),
                'u\'{0}\''.format(
                    model_map['table']): 'MODEL_MAP[\'{0}\'][\'table\']'.format(
                    model),
                'u\'{0}\''.format(model_map[
                                      'model_lower']): 'MODEL_MAP[\'{0}\'][\'model_lower\']'.format(
                    model),
                'u\'{0}\''.format(
                    model_map['app']): 'MODEL_MAP[\'{0}\'][\'app\']'.format(
                    model),
                '[\'{0}\']'.format(
                    model_map['app']): '[MODEL_MAP[\'{0}\'][\'app\']]'.format(
                    model),
                'to=orm[\'{0}\']'.format(model_map[
                                             'model']): 'to=orm[MODEL_MAP[\'{0}\'][\'model\']]'.format(
                    model),
                '\'object_name\': \'{0}\''.format(model_map[
                                                      'class']): '\'object_name\': MODEL_MAP[\'{0}\'][\'class\']'.format(
                    model)
            }
            file_contents = reduce(lambda x, y: x.replace(y, mapping[y]),
                                   mapping, file_contents)
        # End Custom Bluebottle

        # Deal with update mode as late as possible, avoid a rollback as long
        # as something else can go wrong.
        if update:
            last_migration = migrations[-1]
            if MigrationHistory.objects.filter(applied__isnull=False,
                                               app_name=app,
                                               migration=last_migration.name()):
                print(
                    "Migration to be updated, %s, is already applied, rolling it back now..." % last_migration.name(),
                    file=sys.stderr)
                migrate_app(migrations, 'current-1', verbosity=verbosity)
            for ext in ('py', 'pyc'):
                old_filename = "%s.%s" % (
                    os.path.join(migrations.migrations_dir(),
                                 last_migration.filename), ext)
                if os.path.isfile(old_filename):
                    os.unlink(old_filename)
            migrations.remove(last_migration)

        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)

        # - is a special name which means 'print to stdout'
        if name == "-":
            print(file_contents)
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename),
                      "w")
            fp.write(file_contents)
            fp.close()
            verb = 'Updated' if update else 'Created'
            if empty:
                print(
                    "%s %s. You must now edit this migration and add the code for each direction." % (
                        verb, new_filename), file=sys.stderr)
            else:
                print(
                    "%s %s. You can now apply this migration with: ./manage.py migrate %s" % (
                        verb, new_filename, app), file=sys.stderr)
Exemplo n.º 43
0
    def handle(self, app=None, name="", freeze_list=None, stdout=False,
               verbosity=1, **options):

        # Any supposed lists that are None become empty lists
        freeze_list = freeze_list or []

        # --stdout means name = -
        if stdout:
            name = "-"

        # Only allow valid names
        if re.search('[^_\w]', name) and name != "-":
            self.error(
                "Migration names should contain only alphanumeric characters and underscores.")

        # if not name, there's an error
        if not name:
            self.error(
                "You must provide a name for this migration\n" + self.usage_str)

        if not app:
            self.error(
                "You must provide an app to create a migration for.\n" + self.usage_str)

        # Get the Migrations for this app (creating the migrations dir if needed)
        migrations = Migrations(app, force_creation=True,
                                verbose_creation=verbosity > 0)

        # See what filename is next in line. We assume they use numbers.
        new_filename = migrations.next_filename(name)

        # Work out which apps to freeze
        apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)

        # So, what's in this file, then?
        file_contents = MIGRATION_TEMPLATE % {
            "frozen_models": freezer.freeze_apps_to_string(apps_to_freeze),
            "complete_apps": apps_to_freeze and "complete_apps = [%s]" % (
                ", ".join(map(repr, apps_to_freeze))) or ""
        }

        # Custom Bluebottle
        # We find and replace the base apps with our mapped models
        for model in MODEL_MAP:
            model_map = MODEL_MAP[model]
            mapping = {
                'u"orm[\'{0}\']"'.format(model_map[
                                             'model']): '"orm[\'{0}\']".format(MODEL_MAP[\'{1}\'][\'model\'])'.format(
                    '{0}', model),
                'u\'{0}\''.format(
                    model_map['table']): 'MODEL_MAP[\'{0}\'][\'table\']'.format(
                    model),
                'u\'{0}\''.format(model_map[
                                      'model_lower']): 'MODEL_MAP[\'{0}\'][\'model_lower\']'.format(
                    model),
                'u\'{0}\''.format(
                    model_map['app']): 'MODEL_MAP[\'{0}\'][\'app\']'.format(
                    model),
                '[\'{0}\']'.format(
                    model_map['app']): '[MODEL_MAP[\'{0}\'][\'app\']]'.format(
                    model),
                'to=orm[\'{0}\']'.format(model_map[
                                             'model']): 'to=orm[MODEL_MAP[\'{0}\'][\'model\']]'.format(
                    model),
                '\'object_name\': \'{0}\''.format(model_map[
                                                      'class']): '\'object_name\': MODEL_MAP[\'{0}\'][\'class\']'.format(
                    model)
            }
            file_contents = reduce(lambda x, y: x.replace(y, mapping[y]),
                                   mapping, file_contents)

        # End Custom Bluebottle

        # - is a special name which means 'print to stdout'
        if name == "-":
            print(file_contents)
        # Write the migration file if the name isn't -
        else:
            fp = open(os.path.join(migrations.migrations_dir(), new_filename),
                      "w")
            fp.write(file_contents)
            fp.close()
            print("Created %s." % new_filename, file=sys.stderr)