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
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
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: for app in app_list: app_label = app.__name__.split('.')[-2] if hint: evolutions = [] hinted_evolution = diff.evolution() temp_mutations = hinted_evolution.get(app_label, []) else: evolutions = get_unapplied_evolutions(app, database) temp_mutations = get_mutations(app, evolutions, database) mutations = [ mutation for mutation in temp_mutations if mutation.is_mutable(app_label, database_sig, database) ] if mutations: app_sql = ['-- Evolve application %s' % app_label] evolution_required = True for mutation in mutations: # Only compile SQL if we want to show it if compile_sql or execute:
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: for app in app_list: app_label = app.__name__.split('.')[-2] if hint: evolutions = [] hinted_evolution = diff.evolution() temp_mutations = hinted_evolution.get(app_label, []) else: evolutions = get_unapplied_evolutions(app, database) temp_mutations = get_mutations(app, evolutions, database) mutations = [ mutation for mutation in temp_mutations if mutation.is_mutable(app_label, database_sig, database) ] if mutations: app_sql = ['-- Evolve application %s' % app_label] evolution_required = True for mutation in mutations: # Only compile SQL if we want to show it if compile_sql or execute: app_sql.extend(
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 = [] hinted_evolution = diff.evolution() mutations = hinted_evolution.get(app_label,[]) else: evolutions = get_unapplied_evolutions(app) mutations = get_mutations(app, evolutions) if mutations: app_sql = ['-- Evolve application %s' % app_label] evolution_required = True for mutation in mutations: # Only compile SQL if we want to show it if compile_sql or execute: app_sql.extend(mutation.mutate(app_label, database_sig)) # Now run the simulation, which will modify the signatures try: mutation.simulate(app_label, database_sig) except CannotSimulate: simulated = False
def _on_app_models_updated(app, verbosity=1, using=DEFAULT_DB_ALIAS, **kwargs): """Handler for when an app's models were updated. This is called in response to a syncdb or migrate operation for an app. It will install baselines for any new models, record the changes in the evolution history, and notify the user if any of the changes require an evolution. Args: app (module): The app models module that was updated. verbosity (int, optional): The verbosity used to control output. This will have been provided by the syncdb or migrate command. using (str, optional): The database being updated. **kwargs (dict): Additional keyword arguments provided by the signal handler for the syncdb or migrate operation. """ project_sig = ProjectSignature.from_database(using) try: latest_version = Version.objects.current_version(using=using) except Version.DoesNotExist: # We need to create a baseline version. if verbosity > 0: print("Installing baseline version") latest_version = Version(signature=project_sig) latest_version.save(using=using) for a in get_apps(): _install_baseline(app=a, latest_version=latest_version, using=using, verbosity=verbosity) unapplied = get_unapplied_evolutions(app, using) if unapplied: print( style.NOTICE('There are unapplied evolutions for %s.' % get_app_label(app))) # 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 is get_app('django_evolution'): old_project_sig = 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 new_app_sig in project_sig.app_sigs: app_id = new_app_sig.app_id old_app_sig = old_project_sig.get_app_sig(app_id) if old_app_sig is None: # App has been added old_project_sig.add_app_sig(new_app_sig.clone()) new_apps.append(app_id) changed = True else: for new_model_sig in new_app_sig.model_sigs: model_name = new_model_sig.model_name old_model_sig = old_app_sig.get_model_sig(model_name) if old_model_sig is None: # Model has been added old_app_sig.add_model_sig( project_sig.get_app_sig(app_id).get_model_sig( model_name).clone()) changed = True if changed: if verbosity > 0: print("Adding baseline version for new models") latest_version = Version(signature=old_project_sig) latest_version.save(using=using) for app_name in new_apps: app = get_app(app_name, True) if app: _install_baseline(app=app, latest_version=latest_version, using=using, verbosity=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_project_sig, project_sig) if not diff.is_empty(): print( style.NOTICE( 'Project signature has changed - an evolution is required') ) if verbosity > 1: print(diff)
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
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
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 = [] hinted_evolution = diff.evolution() mutations = hinted_evolution.get(app_label, []) else: evolutions = get_unapplied_evolutions(app) mutations = get_mutations(app, evolutions) if mutations: app_sql = ['-- Evolve application %s' % app_label] evolution_required = True for mutation in mutations: # Only compile SQL if we want to show it if compile_sql or execute: app_sql.extend( mutation.mutate(app_label, database_sig)) # Now run the simulation, which will modify the signatures try: mutation.simulate(app_label, database_sig) except CannotSimulate: