Esempio n. 1
0
def get_mutations(app, evolution_labels, database):
    """
    Obtain the list of mutations described by the named evolutions.
    """
    # For each item in the evolution sequence. Check each item to see if it is
    # a python file or an sql file.
    try:
        app_name = '.'.join(app.__name__.split('.')[:-1])

        if app_name in BUILTIN_SEQUENCES:
            module_name = 'django_evolution.builtin_evolutions'
        else:
            module_name = '%s.evolutions' % app_name

        evolution_module = __import__(module_name, {}, {}, [''])
    except ImportError:
        return []

    mutations = []

    for label in evolution_labels:
        directory_name = os.path.dirname(evolution_module.__file__)

        # The first element is used for compatibility purposes.
        filenames = [
            os.path.join(directory_name, label + '.sql'),
            os.path.join(directory_name, "%s_%s.sql" % (database, label)),
        ]

        found = False

        for filename in filenames:
            if os.path.exists(filename):
                sql = []
                sql_file = open(sql_file_name)

                for line in sql_file:
                    sql.append(line)

                mutations.append(SQLMutation(label, sql))

                found = True
                break

        if not found:
            try:
                module_name = [evolution_module.__name__, label]
                module = __import__('.'.join(module_name), {}, {},
                                    [module_name])
                mutations.extend(module.MUTATIONS)
            except ImportError:
                raise EvolutionException(
                    'Error: Failed to find an SQL or Python evolution named %s'
                    % label)

    if is_multi_db():
        latest_version = Version.objects.using(database).latest('when')
    else:
        latest_version = Version.objects.latest('when')

    app_label = app.__name__.split('.')[-2]
    old_proj_sig = pickle.loads(str(latest_version.signature))
    proj_sig = create_project_sig(database)

    if app_label in old_proj_sig and app_label in proj_sig:
        # We want to go through now and make sure we're only applying
        # evolutions for models where the signature is different between
        # what's stored and what's current.
        #
        # The reason for this is that we may have just installed a baseline,
        # which would have the up-to-date signature, and we might be trying
        # to apply evolutions on top of that (which would already be applied).
        # These would generate errors. So, try hard to prevent that.
        old_app_sig = old_proj_sig[app_label]
        app_sig = proj_sig[app_label]

        changed_models = set()

        # Find the list of models in the latest signature of this app
        # that aren't in the old signature.
        for model_name, model_sig in app_sig.iteritems():
            if (model_name not in old_app_sig
                    or old_app_sig[model_name] != model_sig):
                changed_models.add(model_name)

        # Now do the same for models in the old signature, in case the
        # model has been deleted.
        for model_name, model_sig in old_app_sig.iteritems():
            if model_name not in app_sig:
                changed_models.add(model_name)

        # We should now have a full list of which models changed. Filter
        # the list of mutations appropriately.
        mutations = [
            mutation for mutation in mutations
            if (not hasattr(mutation, 'model_name')
                or mutation.model_name in changed_models)
        ]

    return mutations
Esempio n. 2
0
def evolution(app, created_models, verbosity=1, **kwargs):
    """
    A hook into syncdb's post_syncdb signal, that is used to notify the user
    if a model evolution is necessary.
    """
    default_db = None
    if is_multi_db():
        from django.db.utils import DEFAULT_DB_ALIAS
        default_db = DEFAULT_DB_ALIAS

    db = kwargs.get('db', default_db)
    proj_sig = create_project_sig(db)
    signature = pickle.dumps(proj_sig)

    using_args = {}

    if is_multi_db():
        using_args['using'] = db

    try:
        if is_multi_db():
            latest_version = \
                django_evolution.Version.objects.using(db).latest('when')
        else:
            latest_version = django_evolution.Version.objects.latest('when')
    except django_evolution.Version.DoesNotExist:
        # We need to create a baseline version.
        if verbosity > 0:
            print "Installing baseline version"

        latest_version = django_evolution.Version(signature=signature)
        latest_version.save(**using_args)

        for a in get_apps():
            install_baseline(a, latest_version, using_args, verbosity)

    unapplied = get_unapplied_evolutions(app, db)

    if unapplied:
        print style.NOTICE('There are unapplied evolutions for %s.'
                           % app.__name__.split('.')[-2])

    # Evolutions are checked over the entire project, so we only need to check
    # once. We do this check when Django Evolutions itself is synchronized.
    if app == django_evolution:
        old_proj_sig = pickle.loads(str(latest_version.signature))

        # If any models or apps have been added, a baseline must be set
        # for those new models
        changed = False
        new_apps = []

        for app_name, new_app_sig in proj_sig.items():
            if app_name == '__version__':
                # Ignore the __version__ tag
                continue

            old_app_sig = old_proj_sig.get(app_name, None)

            if old_app_sig is None:
                # App has been added
                old_proj_sig[app_name] = proj_sig[app_name]
                new_apps.append(app_name)
                changed = True
            else:
                for model_name, new_model_sig in new_app_sig.items():
                    old_model_sig = old_app_sig.get(model_name, None)

                    if old_model_sig is None:
                        # Model has been added
                        old_proj_sig[app_name][model_name] = \
                            proj_sig[app_name][model_name]
                        changed = True

        if changed:
            if verbosity > 0:
                print "Adding baseline version for new models"

            latest_version = \
                django_evolution.Version(signature=pickle.dumps(old_proj_sig))
            latest_version.save(**using_args)

            for app_name in new_apps:
                install_baseline(get_app(app_name), latest_version, using_args,
                                 verbosity)

        # TODO: Model introspection step goes here.
        # # If the current database state doesn't match the last
        # # saved signature (as reported by latest_version),
        # # then we need to update the Evolution table.
        # actual_sig = introspect_project_sig()
        # acutal = pickle.dumps(actual_sig)
        # if actual != latest_version.signature:
        #     nudge = Version(signature=actual)
        #     nudge.save()
        #     latest_version = nudge

        diff = Diff(old_proj_sig, proj_sig)

        if not diff.is_empty():
            print style.NOTICE(
                'Project signature has changed - an evolution is required')

            if verbosity > 1:
                old_proj_sig = pickle.loads(str(latest_version.signature))
                print diff
Esempio n. 3
0
def evolution(app, created_models, verbosity=1, **kwargs):
    """
    A hook into syncdb's post_syncdb signal, that is used to notify the user
    if a model evolution is necessary.
    """
    default_db = DEFAULT_DB_ALIAS

    db = kwargs.get('db', default_db)
    proj_sig = create_project_sig(db)
    signature = pickle.dumps(proj_sig)

    using_args = {
        'using': db,
    }

    try:
        latest_version = \
            django_evolution.Version.objects.current_version(using=db)
    except django_evolution.Version.DoesNotExist:
        # We need to create a baseline version.
        if verbosity > 0:
            print "Installing baseline version"

        latest_version = django_evolution.Version(signature=signature)
        latest_version.save(**using_args)

        for a in get_apps():
            install_baseline(a, latest_version, using_args, verbosity)

    unapplied = get_unapplied_evolutions(app, db)

    if unapplied:
        print style.NOTICE('There are unapplied evolutions for %s.'
                           % app.__name__.split('.')[-2])

    # Evolutions are checked over the entire project, so we only need to check
    # once. We do this check when Django Evolutions itself is synchronized.
    if app == django_evolution:
        old_proj_sig = pickle.loads(str(latest_version.signature))

        # If any models or apps have been added, a baseline must be set
        # for those new models
        changed = False
        new_apps = []

        for app_name, new_app_sig in proj_sig.items():
            if app_name == '__version__':
                # Ignore the __version__ tag
                continue

            old_app_sig = old_proj_sig.get(app_name, None)

            if old_app_sig is None:
                # App has been added
                old_proj_sig[app_name] = proj_sig[app_name]
                new_apps.append(app_name)
                changed = True
            else:
                for model_name, new_model_sig in new_app_sig.items():
                    old_model_sig = old_app_sig.get(model_name, None)

                    if old_model_sig is None:
                        # Model has been added
                        old_proj_sig[app_name][model_name] = \
                            proj_sig[app_name][model_name]
                        changed = True

        if changed:
            if verbosity > 0:
                print "Adding baseline version for new models"

            latest_version = \
                django_evolution.Version(signature=pickle.dumps(old_proj_sig))
            latest_version.save(**using_args)

            for app_name in new_apps:
                app = get_app(app_name, True)

                if app:
                    install_baseline(app, latest_version, using_args,
                                     verbosity)

        # TODO: Model introspection step goes here.
        # # If the current database state doesn't match the last
        # # saved signature (as reported by latest_version),
        # # then we need to update the Evolution table.
        # actual_sig = introspect_project_sig()
        # acutal = pickle.dumps(actual_sig)
        # if actual != latest_version.signature:
        #     nudge = Version(signature=actual)
        #     nudge.save()
        #     latest_version = nudge

        diff = Diff(old_proj_sig, proj_sig)

        if not diff.is_empty():
            print style.NOTICE(
                'Project signature has changed - an evolution is required')

            if verbosity > 1:
                old_proj_sig = pickle.loads(str(latest_version.signature))
                print diff
Esempio n. 4
0
                                   'executing evolutions.')
            try:
                app_list = [get_app(app_label) for app_label in app_labels]
            except (ImproperlyConfigured, ImportError), e:
                raise CommandError("%s. Are you sure your INSTALLED_APPS "
                                   "setting is correct?" % e)
        else:
            app_list = get_apps()

        # Iterate over all applications running the mutations
        evolution_required = False
        simulated = True
        sql = []
        new_evolutions = []

        current_proj_sig = create_project_sig(database)
        current_signature = pickle.dumps(current_proj_sig)

        try:
            if is_multi_db():
                latest_version = Version.objects.using(database).latest('when')
            else:
                latest_version = Version.objects.latest('when')

            database_sig = pickle.loads(str(latest_version.signature))
            diff = Diff(database_sig, current_proj_sig)
        except Evolution.DoesNotExist:
            raise CommandError("Can't evolve yet. Need to set an "
                               "evolution baseline.")

        try:
Esempio n. 5
0
                                   'executing evolutions.')
            try:
                app_list = [get_app(app_label) for app_label in app_labels]
            except (ImproperlyConfigured, ImportError), e:
                raise CommandError("%s. Are you sure your INSTALLED_APPS "
                                   "setting is correct?" % e)
        else:
            app_list = get_apps()

        # Iterate over all applications running the mutations
        evolution_required = False
        simulated = True
        sql = []
        new_evolutions = []

        current_proj_sig = create_project_sig(database)
        current_signature = pickle.dumps(current_proj_sig)

        try:
            if is_multi_db():
                latest_version = Version.objects.using(database).latest('when')
            else:
                latest_version = Version.objects.latest('when')

            database_sig = pickle.loads(str(latest_version.signature))
            diff = Diff(database_sig, current_proj_sig)
        except Evolution.DoesNotExist:
            raise CommandError("Can't evolve yet. Need to set an "
                               "evolution baseline.")

        try:
Esempio n. 6
0
def get_mutations(app, evolution_labels, database):
    """
    Obtain the list of mutations described by the named evolutions.
    """
    # For each item in the evolution sequence. Check each item to see if it is
    # a python file or an sql file.
    try:
        app_name = '.'.join(app.__name__.split('.')[:-1])

        if app_name in BUILTIN_SEQUENCES:
            module_name = 'django_evolution.builtin_evolutions'
        else:
            module_name = '%s.evolutions' % app_name

        evolution_module = __import__(module_name, {}, {}, [''])
    except ImportError:
        return []

    mutations = []

    for label in evolution_labels:
        directory_name = os.path.dirname(evolution_module.__file__)

        # The first element is used for compatibility purposes.
        filenames = [
            os.path.join(directory_name, label + '.sql'),
            os.path.join(directory_name, "%s_%s.sql" % (database, label)),
        ]

        found = False

        for filename in filenames:
            if os.path.exists(filename):
                sql = []
                sql_file = open(sql_file_name)

                for line in sql_file:
                    sql.append(line)

                mutations.append(SQLMutation(label, sql))

                found = True
                break

        if not found:
            try:
                module_name = [evolution_module.__name__, label]
                module = __import__('.'.join(module_name),
                                    {}, {}, [module_name]);
                mutations.extend(module.MUTATIONS)
            except ImportError:
                raise EvolutionException(
                    'Error: Failed to find an SQL or Python evolution named %s'
                    % label)

    if is_multi_db():
        latest_version = Version.objects.using(database).latest('when')
    else:
        latest_version = Version.objects.latest('when')

    app_label = app.__name__.split('.')[-2]
    old_proj_sig = pickle.loads(str(latest_version.signature))
    proj_sig = create_project_sig(database)

    if app_label in old_proj_sig and app_label in proj_sig:
        # We want to go through now and make sure we're only applying
        # evolutions for models where the signature is different between
        # what's stored and what's current.
        #
        # The reason for this is that we may have just installed a baseline,
        # which would have the up-to-date signature, and we might be trying
        # to apply evolutions on top of that (which would already be applied).
        # These would generate errors. So, try hard to prevent that.
        old_app_sig = old_proj_sig[app_label]
        app_sig = proj_sig[app_label]

        changed_models = set()

        # Find the list of models in the latest signature of this app
        # that aren't in the old signature.
        for model_name, model_sig in app_sig.iteritems():
            if (model_name not in old_app_sig or
                old_app_sig[model_name] != model_sig):
                changed_models.add(model_name)

        # Now do the same for models in the old signature, in case the
        # model has been deleted.
        for model_name, model_sig in old_app_sig.iteritems():
            if model_name not in app_sig:
                changed_models.add(model_name)

        # We should now have a full list of which models changed. Filter
        # the list of mutations appropriately.
        mutations = [
            mutation
            for mutation in mutations
            if (not hasattr(mutation, 'model_name') or
                mutation.model_name in changed_models)
        ]

    return mutations
Esempio n. 7
0
            try:
                app_list = [get_app(app_label) for app_label in app_labels]
            except (ImproperlyConfigured, ImportError), e:
                raise CommandError("%s. Are you sure your INSTALLED_APPS "
                                   "setting is correct?" % e)
        else:
            app_list = get_apps()

        # Iterate over all applications running the mutations
        evolution_required = False  #j--------------------变更请求
        simulated = True
        sql = []
        do_actions = []
        new_evolutions = []

        current_proj_sig = create_project_sig(
            database)  #j-------------------当前版本的数据库整体结构
        current_signature = pickle.dumps(current_proj_sig)

        try:
            if is_multi_db():
                latest_version = Version.objects.using(database).latest('when')
            else:
                latest_version = Version.objects.latest('when')

            database_sig = pickle.loads(str(latest_version.signature)
                                        )  #j-------------------得到上一个版本的数据库整体结构
            diff = Diff(database_sig, current_proj_sig)
        except Evolution.DoesNotExist:
            raise CommandError("Can't evolve yet. Need to set an "
                               "evolution baseline.")
Esempio n. 8
0
            if execute:
                raise CommandError('Cannot specify an application name when executing evolutions.')
            try:
                app_list = [get_app(app_label) for app_label in app_labels]
            except (ImproperlyConfigured, ImportError), e:
                raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
        else:
            app_list = get_apps()

        # Iterate over all applications running the mutations
        evolution_required = False
        simulated = True
        sql = []
        new_evolutions = []
        
        current_proj_sig = create_project_sig()
        current_signature = pickle.dumps(current_proj_sig)

        try:
            latest_version = Version.objects.latest('when')
            database_sig = pickle.loads(str(latest_version.signature))
            diff = Diff(database_sig, current_proj_sig)
        except Evolution.DoesNotExist:
            print self.style.ERROR("Can't evolve yet. Need to set an evolution baseline.")
            sys.exit(1)
        
        try:
            for app in app_list:
                app_label = app.__name__.split('.')[-2]
                if hint:
                    evolutions = []
Esempio n. 9
0
            try:
                app_list = [get_app(app_label) for app_label in app_labels]
            except (ImproperlyConfigured, ImportError), e:
                raise CommandError("%s. Are you sure your INSTALLED_APPS "
                                   "setting is correct?" % e)
        else:
            app_list = get_apps()

        # Iterate over all applications running the mutations
        evolution_required = False  #j--------------------变更请求
        simulated = True
        sql = []
        do_actions=[]
        new_evolutions = []

        current_proj_sig = create_project_sig(database)  #j-------------------当前版本的数据库整体结构
        current_signature = pickle.dumps(current_proj_sig)

        try:
            if is_multi_db():
                latest_version = Version.objects.using(database).latest('when')
            else:
                latest_version = Version.objects.latest('when')

            database_sig = pickle.loads(str(latest_version.signature))  #j-------------------得到上一个版本的数据库整体结构
            diff = Diff(database_sig, current_proj_sig)
        except Evolution.DoesNotExist:
            raise CommandError("Can't evolve yet. Need to set an "
                               "evolution baseline.")

        try:
Esempio n. 10
0
def evolution(app, created_models, verbosity=1, **kwargs):
    """
    A hook into syncdb's post_syncdb signal, that is used to notify the user
    if a model evolution is necessary.
    """
    proj_sig = create_project_sig()
    signature = pickle.dumps(proj_sig)

    try:
        latest_version = django_evolution.Version.objects.latest('when')
    except django_evolution.Version.DoesNotExist:
        # We need to create a baseline version.
        if verbosity > 0:
            print "Installing baseline version"

        latest_version = django_evolution.Version(signature=signature)
        latest_version.save()

        for a in get_apps():
            app_label = a.__name__.split('.')[-2]
            sequence = get_evolution_sequence(a)
            if sequence:
                if verbosity > 0:
                    print 'Evolutions in %s baseline:' % app_label,', '.join(sequence)
            for evo_label in sequence:
                evolution = django_evolution.Evolution(app_label=app_label, 
                                                       label=evo_label,
                                                       version=latest_version)
                evolution.save()

    unapplied = get_unapplied_evolutions(app)
    if unapplied:
        print style.NOTICE('There are unapplied evolutions for %s.' % app.__name__.split('.')[-2])
        
    # Evolutions are checked over the entire project, so we only need to 
    # check once. We do this check when Django Evolutions itself is synchronized.
    if app == django_evolution:        
        old_proj_sig = pickle.loads(str(latest_version.signature))
        
        # If any models have been added, a baseline must be set 
        # for those new models
        changed = False
        for app_name, new_app_sig in proj_sig.items():
            if app_name == '__version__':
                # Ignore the __version__ tag
                continue
            old_app_sig = old_proj_sig.get(app_name, None)
            if old_app_sig is None:
                # App has been added
                old_proj_sig[app_name] = proj_sig[app_name]
                changed = True
                continue
            for model_name, new_model_sig in new_app_sig.items():
                old_model_sig = old_app_sig.get(model_name, None)
                if old_model_sig is None:
                    # Model has been added
                    old_proj_sig[app_name][model_name] = proj_sig[app_name][model_name]
                    changed = True
        
        if changed:
            if verbosity > 0:
                print "Adding baseline version for new models"
            latest_version = django_evolution.Version(signature=pickle.dumps(old_proj_sig))
            latest_version.save()

        # TODO: Model introspection step goes here. 
        # # If the current database state doesn't match the last 
        # # saved signature (as reported by latest_version),
        # # then we need to update the Evolution table.
        # actual_sig = introspect_project_sig()
        # acutal = pickle.dumps(actual_sig)
        # if actual != latest_version.signature:
        #     nudge = Version(signature=actual)
        #     nudge.save()
        #     latest_version = nudge
        
        diff = Diff(old_proj_sig, proj_sig)
        if not diff.is_empty():
            print style.NOTICE('Project signature has changed - an evolution is required')
            if verbosity > 1:
                old_proj_sig = pickle.loads(str(latest_version.signature))
                print diff
Esempio n. 11
0
def evolution(app, created_models, verbosity=1, **kwargs):
    """
    A hook into syncdb's post_syncdb signal, that is used to notify the user
    if a model evolution is necessary.
    """
    proj_sig = create_project_sig()
    signature = pickle.dumps(proj_sig)

    try:
        latest_version = django_evolution.Version.objects.latest('when')
    except django_evolution.Version.DoesNotExist:
        # We need to create a baseline version.
        if verbosity > 0:
            print "Installing baseline version"

        latest_version = django_evolution.Version(signature=signature)
        latest_version.save()

        for a in get_apps():
            app_label = a.__name__.split('.')[-2]
            sequence = get_evolution_sequence(a)
            if sequence:
                if verbosity > 0:
                    print 'Evolutions in %s baseline:' % app_label, ', '.join(
                        sequence)
            for evo_label in sequence:
                evolution = django_evolution.Evolution(app_label=app_label,
                                                       label=evo_label,
                                                       version=latest_version)
                evolution.save()

    unapplied = get_unapplied_evolutions(app)
    if unapplied:
        print style.NOTICE('There are unapplied evolutions for %s.' %
                           app.__name__.split('.')[-2])

    # Evolutions are checked over the entire project, so we only need to
    # check once. We do this check when Django Evolutions itself is synchronized.
    if app == django_evolution:
        old_proj_sig = pickle.loads(str(latest_version.signature))

        # If any models have been added, a baseline must be set
        # for those new models
        changed = False
        for app_name, new_app_sig in proj_sig.items():
            if app_name == '__version__':
                # Ignore the __version__ tag
                continue
            old_app_sig = old_proj_sig.get(app_name, None)
            if old_app_sig is None:
                # App has been added
                old_proj_sig[app_name] = proj_sig[app_name]
                changed = True
                continue
            for model_name, new_model_sig in new_app_sig.items():
                old_model_sig = old_app_sig.get(model_name, None)
                if old_model_sig is None:
                    # Model has been added
                    old_proj_sig[app_name][model_name] = proj_sig[app_name][
                        model_name]
                    changed = True

        if changed:
            if verbosity > 0:
                print "Adding baseline version for new models"
            latest_version = django_evolution.Version(
                signature=pickle.dumps(old_proj_sig))
            latest_version.save()

        # TODO: Model introspection step goes here.
        # # If the current database state doesn't match the last
        # # saved signature (as reported by latest_version),
        # # then we need to update the Evolution table.
        # actual_sig = introspect_project_sig()
        # acutal = pickle.dumps(actual_sig)
        # if actual != latest_version.signature:
        #     nudge = Version(signature=actual)
        #     nudge.save()
        #     latest_version = nudge

        diff = Diff(old_proj_sig, proj_sig)
        if not diff.is_empty():
            print style.NOTICE(
                'Project signature has changed - an evolution is required')
            if verbosity > 1:
                old_proj_sig = pickle.loads(str(latest_version.signature))
                print diff
Esempio n. 12
0
            try:
                app_list = [get_app(app_label) for app_label in app_labels]
            except (ImproperlyConfigured, ImportError), e:
                raise CommandError(
                    "%s. Are you sure your INSTALLED_APPS setting is correct?"
                    % e)
        else:
            app_list = get_apps()

        # Iterate over all applications running the mutations
        evolution_required = False
        simulated = True
        sql = []
        new_evolutions = []

        current_proj_sig = create_project_sig()
        current_signature = pickle.dumps(current_proj_sig)

        try:
            latest_version = Version.objects.latest('when')
            database_sig = pickle.loads(str(latest_version.signature))
            diff = Diff(database_sig, current_proj_sig)
        except Evolution.DoesNotExist:
            print self.style.ERROR(
                "Can't evolve yet. Need to set an evolution baseline.")
            sys.exit(1)

        try:
            for app in app_list:
                app_label = app.__name__.split('.')[-2]
                if hint: