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, 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.º 3
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.º 4
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.º 5
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.º 6
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.º 7
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.º 8
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.º 9
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)
Exemplo n.º 10
0
class Command(BaseCommand):
    __doc__ = help = _help

    option_list = BaseCommand.option_list + (
        make_option('--database',
                    action='store',
                    dest='database',
                    default=DEFAULT_DB_ALIAS,
                    help='Nominates a specific '
                    'database to dump fixtures from. Defaults to the '
                    '"default" database.'),
        make_option('--backup-path',
                    action='store',
                    dest='backup_path',
                    help='Define a non-temporary path for the migration '
                    'backup.'),
        make_option('--no-fake',
                    action='store_true',
                    help='Prevents the new '
                    'migration from being immediately faked in the database.'))

    def handle(self,
               migration_suffix=METADATA_MIGRATION_SUFFIX,
               fixture_suffix=METADATA_FIXTURE_SUFFIX,
               **options):
        database = options.get('database')
        verbosity = options.get('verbosity')
        backup_path = options.get('backup_path')
        no_fake = options.get('no_fake')

        try:
            fixture_dir = backup.get_fixture_dir()
        except ImproperlyConfigured, e:
            raise CommandError(e.message)

        if not os.path.exists(fixture_dir):
            os.makedirs(fixture_dir)
            log.info(u'Created fixture directory: {0}'.format(fixture_dir))
        elif not os.path.isdir(fixture_dir):
            raise CommandError(u'The metadata fixture directory {0}.. is not '
                               'a directory.'.format(fixture_dir))

        # Only allow valid names
        if re.search('[^_\w]', migration_suffix):
            raise CommandError('Migration names should contain only '
                               'alphanumeric characters and underscores.')

        fixture_name = backup.next_fixture_name(fixture_suffix, fixture_dir)
        backup.create_fixture(fixture_name, using=database)

        if verbosity > 1:
            log.info(u'Created fixture {0}'.format(fixture_name))

        # Get the last migration for avocado to insert it as a dependency
        avocado_migrations = migration.Migrations('avocado',
                                                  force_creation=False)
        avocado_migration_name = avocado_migrations[-1].name()

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

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

        # Normally, South would freeze the Avocado models(since we are
        # dependent on them) along with this app's models and store the frozen
        # representation in the migration. Since we are building the
        # migration ourselves, we need to freeze and write the models to the
        # migration.
        frozen_models = freezer.freeze_apps_to_string(
            ['avocado', settings.METADATA_MIGRATION_APP])

        file_contents = METADATA_MIGRATION_TEMPLATE.format(
            latest_avocado_migration=avocado_migration_name,
            fixture_name=repr(fixture_name),
            backup_path=(backup_path and repr(backup_path) or backup_path),
            using=repr(database),
            frozen_models=frozen_models)

        file_path = os.path.join(migrations.migrations_dir(), next_filename)

        with open(file_path, 'w') as fout:
            fout.write(file_contents)

        log.info(u'Created migration {0}'.format(next_filename))

        if not no_fake:
            # Clear and reload migrations..
            [migrations.pop() for _ in xrange(len(migrations))]
            migrations._load_migrations_module(
                migrations.application.migrations)

            # Fake migrations up to the current created one..
            management.call_command('migrate',
                                    settings.METADATA_MIGRATION_APP,
                                    os.path.splitext(next_filename)[0],
                                    fake=True,
                                    database=database,
                                    verbosity=0)

            log.info('Faked migrations up to the current one')