diff options
Diffstat (limited to 'lib/python2.7/site-packages/south')
117 files changed, 0 insertions, 11485 deletions
diff --git a/lib/python2.7/site-packages/south/__init__.py b/lib/python2.7/site-packages/south/__init__.py deleted file mode 100644 index 86642c6..0000000 --- a/lib/python2.7/site-packages/south/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -""" -South - Useable migrations for Django apps -""" - -__version__ = "0.8.4" -__authors__ = [ - "Andrew Godwin <andrew@aeracode.org>", - "Andy McCurdy <andy@andymccurdy.com>" -] diff --git a/lib/python2.7/site-packages/south/creator/__init__.py b/lib/python2.7/site-packages/south/creator/__init__.py deleted file mode 100644 index 96a1a80..0000000 --- a/lib/python2.7/site-packages/south/creator/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -The creator module is responsible for making new migration files, either -as blank templates or autodetecting changes. It contains code that used to -all be in startmigration.py. -""" diff --git a/lib/python2.7/site-packages/south/creator/actions.py b/lib/python2.7/site-packages/south/creator/actions.py deleted file mode 100644 index 2ffc8ca..0000000 --- a/lib/python2.7/site-packages/south/creator/actions.py +++ /dev/null @@ -1,559 +0,0 @@ -""" -Actions - things like 'a model was removed' or 'a field was changed'. -Each one has a class, which can take the action description and insert code -blocks into the forwards() and backwards() methods, in the right place. -""" - -from __future__ import print_function - -import sys - -from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT -from django.db.models.fields import FieldDoesNotExist, NOT_PROVIDED, CharField, TextField - -from south.modelsinspector import value_clean -from south.creator.freezer import remove_useless_attributes, model_key -from south.utils import datetime_utils -from south.utils.py3 import raw_input - - -class Action(object): - """ - Generic base Action class. Contains utility methods for inserting into - the forwards() and backwards() method lists. - """ - - prepend_forwards = False - prepend_backwards = False - - def forwards_code(self): - raise NotImplementedError - - def backwards_code(self): - raise NotImplementedError - - def add_forwards(self, forwards): - if self.prepend_forwards: - forwards.insert(0, self.forwards_code()) - else: - forwards.append(self.forwards_code()) - - def add_backwards(self, backwards): - if self.prepend_backwards: - backwards.insert(0, self.backwards_code()) - else: - backwards.append(self.backwards_code()) - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - raise NotImplementedError - - @classmethod - def triples_to_defs(cls, fields): - # Turn the (class, args, kwargs) format into a string - for field, triple in fields.items(): - fields[field] = cls.triple_to_def(triple) - return fields - - @classmethod - def triple_to_def(cls, triple): - "Turns a single triple into a definition." - return "self.gf(%r)(%s)" % ( - triple[0], # Field full path - ", ".join(triple[1] + ["%s=%s" % (kwd, val) for kwd, val in triple[2].items()]), # args and kwds - ) - - -class AddModel(Action): - """ - Addition of a model. Takes the Model subclass that is being created. - """ - - FORWARDS_TEMPLATE = ''' - # Adding model '%(model_name)s' - db.create_table(%(table_name)r, ( - %(field_defs)s - )) - db.send_create_signal(%(app_label)r, [%(model_name)r])'''[1:] + "\n" - - BACKWARDS_TEMPLATE = ''' - # Deleting model '%(model_name)s' - db.delete_table(%(table_name)r)'''[1:] + "\n" - - def __init__(self, model, model_def): - self.model = model - self.model_def = model_def - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " + Added model %s.%s" % ( - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - "Produces the code snippet that gets put into forwards()" - field_defs = ",\n ".join([ - "(%r, %s)" % (name, defn) for name, defn - in self.triples_to_defs(self.model_def).items() - ]) + "," - - return self.FORWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "app_label": self.model._meta.app_label, - "field_defs": field_defs, - } - - def backwards_code(self): - "Produces the code snippet that gets put into backwards()" - return self.BACKWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - } - - -class DeleteModel(AddModel): - """ - Deletion of a model. Takes the Model subclass that is being created. - """ - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " - Deleted model %s.%s" % ( - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - return AddModel.backwards_code(self) - - def backwards_code(self): - return AddModel.forwards_code(self) - - -class _NullIssuesField(object): - """ - A field that might need to ask a question about rogue NULL values. - """ - - issue_with_backward_migration = False - irreversible = False - - IRREVERSIBLE_TEMPLATE = ''' - # User chose to not deal with backwards NULL issues for '%(model_name)s.%(field_name)s' - raise RuntimeError("Cannot reverse this migration. '%(model_name)s.%(field_name)s' and its values cannot be restored.") - - # The following code is provided here to aid in writing a correct migration''' - - def deal_with_not_null_no_default(self, field, field_def): - # If it's a CharField or TextField that's blank, skip this step. - if isinstance(field, (CharField, TextField)) and field.blank: - field_def[2]['default'] = repr("") - return - # Oh dear. Ask them what to do. - print(" ? The field '%s.%s' does not have a default specified, yet is NOT NULL." % ( - self.model._meta.object_name, - field.name, - )) - print(" ? Since you are %s, you MUST specify a default" % self.null_reason) - print(" ? value to use for existing rows. Would you like to:") - print(" ? 1. Quit now"+("." if self.issue_with_backward_migration else ", and add a default to the field in models.py" )) - print(" ? 2. Specify a one-off value to use for existing columns now") - if self.issue_with_backward_migration: - print(" ? 3. Disable the backwards migration by raising an exception; you can edit the migration to fix it later") - while True: - choice = raw_input(" ? Please select a choice: ") - if choice == "1": - sys.exit(1) - elif choice == "2": - break - elif choice == "3" and self.issue_with_backward_migration: - break - else: - print(" ! Invalid choice.") - if choice == "2": - self.add_one_time_default(field, field_def) - elif choice == "3": - self.irreversible = True - - def add_one_time_default(self, field, field_def): - # OK, they want to pick their own one-time default. Who are we to refuse? - print(" ? Please enter Python code for your one-off default value.") - print(" ? The datetime module is available, so you can do e.g. datetime.date.today()") - while True: - code = raw_input(" >>> ") - if not code: - print(" ! Please enter some code, or 'exit' (with no quotes) to exit.") - elif code == "exit": - sys.exit(1) - else: - try: - result = eval(code, {}, {"datetime": datetime_utils}) - except (SyntaxError, NameError) as e: - print(" ! Invalid input: %s" % e) - else: - break - # Right, add the default in. - field_def[2]['default'] = value_clean(result) - - def irreversable_code(self, field): - return self.IRREVERSIBLE_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "field_name": field.name, - "field_column": field.column, - } - - -class AddField(Action, _NullIssuesField): - """ - Adds a field to a model. Takes a Model class and the field name. - """ - - null_reason = "adding this field" - - FORWARDS_TEMPLATE = ''' - # Adding field '%(model_name)s.%(field_name)s' - db.add_column(%(table_name)r, %(field_name)r, - %(field_def)s, - keep_default=False)'''[1:] + "\n" - - BACKWARDS_TEMPLATE = ''' - # Deleting field '%(model_name)s.%(field_name)s' - db.delete_column(%(table_name)r, %(field_column)r)'''[1:] + "\n" - - def __init__(self, model, field, field_def): - self.model = model - self.field = field - self.field_def = field_def - - # See if they've made a NOT NULL column but also have no default (far too common) - is_null = self.field.null - default = (self.field.default is not None) and (self.field.default is not NOT_PROVIDED) - - if not is_null and not default: - self.deal_with_not_null_no_default(self.field, self.field_def) - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " + Added field %s on %s.%s" % ( - self.field.name, - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - - return self.FORWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "field_name": self.field.name, - "field_column": self.field.column, - "field_def": self.triple_to_def(self.field_def), - } - - def backwards_code(self): - return self.BACKWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "field_name": self.field.name, - "field_column": self.field.column, - } - - -class DeleteField(AddField): - """ - Removes a field from a model. Takes a Model class and the field name. - """ - - null_reason = "removing this field" - issue_with_backward_migration = True - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " - Deleted field %s on %s.%s" % ( - self.field.name, - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - return AddField.backwards_code(self) - - def backwards_code(self): - if not self.irreversible: - return AddField.forwards_code(self) - else: - return self.irreversable_code(self.field) + AddField.forwards_code(self) - - -class ChangeField(Action, _NullIssuesField): - """ - Changes a field's type/options on a model. - """ - - null_reason = "making this field non-nullable" - - FORWARDS_TEMPLATE = BACKWARDS_TEMPLATE = ''' - # Changing field '%(model_name)s.%(field_name)s' - db.alter_column(%(table_name)r, %(field_column)r, %(field_def)s)''' - - RENAME_TEMPLATE = ''' - # Renaming column for '%(model_name)s.%(field_name)s' to match new field type. - db.rename_column(%(table_name)r, %(old_column)r, %(new_column)r)''' - - def __init__(self, model, old_field, new_field, old_def, new_def): - self.model = model - self.old_field = old_field - self.new_field = new_field - self.old_def = old_def - self.new_def = new_def - - # See if they've changed a not-null field to be null - new_default = (self.new_field.default is not None) and (self.new_field.default is not NOT_PROVIDED) - old_default = (self.old_field.default is not None) and (self.old_field.default is not NOT_PROVIDED) - if self.old_field.null and not self.new_field.null and not new_default: - self.deal_with_not_null_no_default(self.new_field, self.new_def) - if not self.old_field.null and self.new_field.null and not old_default: - self.null_reason = "making this field nullable" - self.issue_with_backward_migration = True - self.deal_with_not_null_no_default(self.old_field, self.old_def) - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " ~ Changed field %s on %s.%s" % ( - self.new_field.name, - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def _code(self, old_field, new_field, new_def): - - output = "" - - if self.old_field.column != self.new_field.column: - output += self.RENAME_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "field_name": new_field.name, - "old_column": old_field.column, - "new_column": new_field.column, - } - - output += self.FORWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "field_name": new_field.name, - "field_column": new_field.column, - "field_def": self.triple_to_def(new_def), - } - - return output - - def forwards_code(self): - return self._code(self.old_field, self.new_field, self.new_def) - - def backwards_code(self): - change_code = self._code(self.new_field, self.old_field, self.old_def) - if not self.irreversible: - return change_code - else: - return self.irreversable_code(self.old_field) + change_code - - -class AddUnique(Action): - """ - Adds a unique constraint to a model. Takes a Model class and the field names. - """ - - FORWARDS_TEMPLATE = ''' - # Adding unique constraint on '%(model_name)s', fields %(field_names)s - db.create_unique(%(table_name)r, %(fields)r)'''[1:] + "\n" - - BACKWARDS_TEMPLATE = ''' - # Removing unique constraint on '%(model_name)s', fields %(field_names)s - db.delete_unique(%(table_name)r, %(fields)r)'''[1:] + "\n" - - prepend_backwards = True - - def __init__(self, model, fields): - self.model = model - self.fields = fields - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " + Added unique constraint for %s on %s.%s" % ( - [x.name for x in self.fields], - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - - return self.FORWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "fields": [field.column for field in self.fields], - "field_names": [field.name for field in self.fields], - } - - def backwards_code(self): - return self.BACKWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "table_name": self.model._meta.db_table, - "fields": [field.column for field in self.fields], - "field_names": [field.name for field in self.fields], - } - - -class DeleteUnique(AddUnique): - """ - Removes a unique constraint from a model. Takes a Model class and the field names. - """ - - prepend_forwards = True - prepend_backwards = False - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " - Deleted unique constraint for %s on %s.%s" % ( - [x.name for x in self.fields], - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - return AddUnique.backwards_code(self) - - def backwards_code(self): - return AddUnique.forwards_code(self) - - -class AddIndex(AddUnique): - """ - Adds an index to a model field[s]. Takes a Model class and the field names. - """ - - FORWARDS_TEMPLATE = ''' - # Adding index on '%(model_name)s', fields %(field_names)s - db.create_index(%(table_name)r, %(fields)r)'''[1:] + "\n" - - BACKWARDS_TEMPLATE = ''' - # Removing index on '%(model_name)s', fields %(field_names)s - db.delete_index(%(table_name)r, %(fields)r)'''[1:] + "\n" - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " + Added index for %s on %s.%s" % ( - [x.name for x in self.fields], - self.model._meta.app_label, - self.model._meta.object_name, - ) - - -class DeleteIndex(AddIndex): - """ - Deletes an index off a model field[s]. Takes a Model class and the field names. - """ - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " + Deleted index for %s on %s.%s" % ( - [x.name for x in self.fields], - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - return AddIndex.backwards_code(self) - - def backwards_code(self): - return AddIndex.forwards_code(self) - - -class AddM2M(Action): - """ - Adds a unique constraint to a model. Takes a Model class and the field names. - """ - - FORWARDS_TEMPLATE = ''' - # Adding M2M table for field %(field_name)s on '%(model_name)s' - m2m_table_name = %(table_name)s - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - (%(left_field)r, models.ForeignKey(orm[%(left_model_key)r], null=False)), - (%(right_field)r, models.ForeignKey(orm[%(right_model_key)r], null=False)) - )) - db.create_unique(m2m_table_name, [%(left_column)r, %(right_column)r])'''[1:] + "\n" - - BACKWARDS_TEMPLATE = ''' - # Removing M2M table for field %(field_name)s on '%(model_name)s' - db.delete_table(%(table_name)s)'''[1:] + "\n" - - def __init__(self, model, field): - self.model = model - self.field = field - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " + Added M2M table for %s on %s.%s" % ( - self.field.name, - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def table_name(self): - # This is part of a workaround for the fact that Django uses - # different shortening for automatically generated m2m table names - # (as opposed to any explicitly specified table name) - f = self.field - explicit = f.db_table - if explicit: - return "%r" % explicit - else: - auto = "%s_%s" % (self.model._meta.db_table, f.name) - return 'db.shorten_name(%r)' % auto - - def forwards_code(self): - - return self.FORWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "field_name": self.field.name, - "table_name": self.table_name(), - "left_field": self.field.m2m_column_name()[:-3], # Remove the _id part - "left_column": self.field.m2m_column_name(), - "left_model_key": model_key(self.model), - "right_field": self.field.m2m_reverse_name()[:-3], # Remove the _id part - "right_column": self.field.m2m_reverse_name(), - "right_model_key": model_key(self.field.rel.to), - } - - def backwards_code(self): - - return self.BACKWARDS_TEMPLATE % { - "model_name": self.model._meta.object_name, - "field_name": self.field.name, - "table_name": self.table_name(), - } - - -class DeleteM2M(AddM2M): - """ - Adds a unique constraint to a model. Takes a Model class and the field names. - """ - - def console_line(self): - "Returns the string to print on the console, e.g. ' + Added field foo'" - return " - Deleted M2M table for %s on %s.%s" % ( - self.field.name, - self.model._meta.app_label, - self.model._meta.object_name, - ) - - def forwards_code(self): - return AddM2M.backwards_code(self) - - def backwards_code(self): - return AddM2M.forwards_code(self) - diff --git a/lib/python2.7/site-packages/south/creator/changes.py b/lib/python2.7/site-packages/south/creator/changes.py deleted file mode 100644 index 6cdbd19..0000000 --- a/lib/python2.7/site-packages/south/creator/changes.py +++ /dev/null @@ -1,506 +0,0 @@ -""" -Contains things to detect changes - either using options passed in on the -commandline, or by using autodetection, etc. -""" - -from __future__ import print_function - -from django.db import models -from django.contrib.contenttypes.generic import GenericRelation -from django.utils.datastructures import SortedDict - -from south.creator.freezer import remove_useless_attributes, freeze_apps, model_key -from south.utils import auto_through -from south.utils.py3 import string_types - -class BaseChanges(object): - """ - Base changes class. - """ - def suggest_name(self): - return '' - - def split_model_def(self, model, model_def): - """ - Given a model and its model def (a dict of field: triple), returns three - items: the real fields dict, the Meta dict, and the M2M fields dict. - """ - real_fields = SortedDict() - meta = SortedDict() - m2m_fields = SortedDict() - for name, triple in model_def.items(): - if name == "Meta": - meta = triple - elif isinstance(model._meta.get_field_by_name(name)[0], models.ManyToManyField): - m2m_fields[name] = triple - else: - real_fields[name] = triple - return real_fields, meta, m2m_fields - - def current_model_from_key(self, key): - app_label, model_name = key.split(".") - return models.get_model(app_label, model_name) - - def current_field_from_key(self, key, fieldname): - app_label, model_name = key.split(".") - # Special, for the magical field from order_with_respect_to - if fieldname == "_order": - field = models.IntegerField() - field.name = "_order" - field.attname = "_order" - field.column = "_order" - field.default = 0 - return field - # Otherwise, normal. - return models.get_model(app_label, model_name)._meta.get_field_by_name(fieldname)[0] - - -class AutoChanges(BaseChanges): - """ - Detects changes by 'diffing' two sets of frozen model definitions. - """ - - # Field types we don't generate add/remove field changes for. - IGNORED_FIELD_TYPES = [ - GenericRelation, - ] - - def __init__(self, migrations, old_defs, old_orm, new_defs): - self.migrations = migrations - self.old_defs = old_defs - self.old_orm = old_orm - self.new_defs = new_defs - - def suggest_name(self): - parts = ["auto"] - for change_name, params in self.get_changes(): - if change_name == "AddModel": - parts.append("add_%s" % params['model']._meta.object_name.lower()) - elif change_name == "DeleteModel": - parts.append("del_%s" % params['model']._meta.object_name.lower()) - elif change_name == "AddField": - parts.append("add_field_%s_%s" % ( - params['model']._meta.object_name.lower(), - params['field'].name, - )) - elif change_name == "DeleteField": - parts.append("del_field_%s_%s" % ( - params['model']._meta.object_name.lower(), - params['field'].name, - )) - elif change_name == "ChangeField": - parts.append("chg_field_%s_%s" % ( - params['model']._meta.object_name.lower(), - params['new_field'].name, - )) - elif change_name == "AddUnique": - parts.append("add_unique_%s_%s" % ( - params['model']._meta.object_name.lower(), - "_".join([x.name for x in params['fields']]), - )) - elif change_name == "DeleteUnique": - parts.append("del_unique_%s_%s" % ( - params['model']._meta.object_name.lower(), - "_".join([x.name for x in params['fields']]), - )) - elif change_name == "AddIndex": - parts.append("add_index_%s_%s" % ( - params['model']._meta.object_name.lower(), - "_".join([x.name for x in params['fields']]), - )) - elif change_name == "DeleteIndex": - parts.append("del_index_%s_%s" % ( - params['model']._meta.object_name.lower(), - "_".join([x.name for x in params['fields']]), - )) - return ("__".join(parts))[:70] - - def get_changes(self): - """ - Returns the difference between the old and new sets of models as a 5-tuple: - added_models, deleted_models, added_fields, deleted_fields, changed_fields - """ - - deleted_models = set() - - # See if anything's vanished - for key in self.old_defs: - if key not in self.new_defs: - # We shouldn't delete it if it was managed=False - old_fields, old_meta, old_m2ms = self.split_model_def(self.old_orm[key], self.old_defs[key]) - if old_meta.get("managed", "True") != "False": - # Alright, delete it. - yield ("DeleteModel", { - "model": self.old_orm[key], - "model_def": old_fields, - }) - # Also make sure we delete any M2Ms it had. - for fieldname in old_m2ms: - # Only delete its stuff if it wasn't a through=. - field = self.old_orm[key + ":" + fieldname] - if auto_through(field): - yield ("DeleteM2M", {"model": self.old_orm[key], "field": field}) - # And any index/uniqueness constraints it had - for attr, operation in (("unique_together", "DeleteUnique"), ("index_together", "DeleteIndex")): - together = eval(old_meta.get(attr, "[]")) - if together: - # If it's only a single tuple, make it into the longer one - if isinstance(together[0], string_types): - together = [together] - # For each combination, make an action for it - for fields in together: - yield (operation, { - "model": self.old_orm[key], - "fields": [self.old_orm[key]._meta.get_field_by_name(x)[0] for x in fields], - }) - # We always add it in here so we ignore it later - deleted_models.add(key) - - # Or appeared - for key in self.new_defs: - if key not in self.old_defs: - # We shouldn't add it if it's managed=False - new_fields, new_meta, new_m2ms = self.split_model_def(self.current_model_from_key(key), self.new_defs[key]) - if new_meta.get("managed", "True") != "False": - yield ("AddModel", { - "model": self.current_model_from_key(key), - "model_def": new_fields, - }) - # Also make sure we add any M2Ms it has. - for fieldname in new_m2ms: - # Only create its stuff if it wasn't a through=. - field = self.current_field_from_key(key, fieldname) - if auto_through(field): - yield ("AddM2M", {"model": self.current_model_from_key(key), "field": field}) - # And any index/uniqueness constraints it has - for attr, operation in (("unique_together", "AddUnique"), ("index_together", "AddIndex")): - together = eval(new_meta.get(attr, "[]")) - if together: - # If it's only a single tuple, make it into the longer one - if isinstance(together[0], string_types): - together = [together] - # For each combination, make an action for it - for fields in together: - yield (operation, { - "model": self.current_model_from_key(key), - "fields": [self.current_model_from_key(key)._meta.get_field_by_name(x)[0] for x in fields], - }) - - # Now, for every model that's stayed the same, check its fields. - for key in self.old_defs: - if key not in deleted_models: - - old_fields, old_meta, old_m2ms = self.split_model_def(self.old_orm[key], self.old_defs[key]) - new_fields, new_meta, new_m2ms = self.split_model_def(self.current_model_from_key(key), self.new_defs[key]) - - # Do nothing for models which are now not managed. - if new_meta.get("managed", "True") == "False": - continue - - # Find fields that have vanished. - for fieldname in old_fields: - if fieldname not in new_fields: - # Don't do it for any fields we're ignoring - field = self.old_orm[key + ":" + fieldname] - field_allowed = True - for field_type in self.IGNORED_FIELD_TYPES: - if isinstance(field, field_type): - field_allowed = False - if field_allowed: - # Looks alright. - yield ("DeleteField", { - "model": self.old_orm[key], - "field": field, - "field_def": old_fields[fieldname], - }) - - # And ones that have appeared - for fieldname in new_fields: - if fieldname not in old_fields: - # Don't do it for any fields we're ignoring - field = self.current_field_from_key(key, fieldname) - field_allowed = True - for field_type in self.IGNORED_FIELD_TYPES: - if isinstance(field, field_type): - field_allowed = False - if field_allowed: - # Looks alright. - yield ("AddField", { - "model": self.current_model_from_key(key), - "field": field, - "field_def": new_fields[fieldname], - }) - - # Find M2Ms that have vanished - for fieldname in old_m2ms: - if fieldname not in new_m2ms: - # Only delete its stuff if it wasn't a through=. - field = self.old_orm[key + ":" + fieldname] - if auto_through(field): - yield ("DeleteM2M", {"model": self.old_orm[key], "field": field}) - - # Find M2Ms that have appeared - for fieldname in new_m2ms: - if fieldname not in old_m2ms: - # Only create its stuff if it wasn't a through=. - field = self.current_field_from_key(key, fieldname) - if auto_through(field): - yield ("AddM2M", {"model": self.current_model_from_key(key), "field": field}) - - # For the ones that exist in both models, see if they were changed - for fieldname in set(old_fields).intersection(set(new_fields)): - # Non-index changes - if self.different_attributes( - remove_useless_attributes(old_fields[fieldname], True, True), - remove_useless_attributes(new_fields[fieldname], True, True)): - yield ("ChangeField", { - "model": self.current_model_from_key(key), - "old_field": self.old_orm[key + ":" + fieldname], - "new_field": self.current_field_from_key(key, fieldname), - "old_def": old_fields[fieldname], - "new_def": new_fields[fieldname], - }) - # Index changes - old_field = self.old_orm[key + ":" + fieldname] - new_field = self.current_field_from_key(key, fieldname) - if not old_field.db_index and new_field.db_index: - # They've added an index. - yield ("AddIndex", { - "model": self.current_model_from_key(key), - "fields": [new_field], - }) - if old_field.db_index and not new_field.db_index: - # They've removed an index. - yield ("DeleteIndex", { - "model": self.old_orm[key], - "fields": [old_field], - }) - # See if their uniques have changed - if old_field.unique != new_field.unique: - # Make sure we look at the one explicitly given to see what happened - if new_field.unique: - yield ("AddUnique", { - "model": self.current_model_from_key(key), - "fields": [new_field], - }) - else: - yield ("DeleteUnique", { - "model": self.old_orm[key], - "fields": [old_field], - }) - - # See if there's any M2Ms that have changed. - for fieldname in set(old_m2ms).intersection(set(new_m2ms)): - old_field = self.old_orm[key + ":" + fieldname] - new_field = self.current_field_from_key(key, fieldname) - # Have they _added_ a through= ? - if auto_through(old_field) and not auto_through(new_field): - yield ("DeleteM2M", {"model": self.old_orm[key], "field": old_field}) - # Have they _removed_ a through= ? - if not auto_through(old_field) and auto_through(new_field): - yield ("AddM2M", {"model": self.current_model_from_key(key), "field": new_field}) - - ## See if the {index,unique}_togethers have changed - for attr, add_operation, del_operation in (("unique_together", "AddUnique", "DeleteUnique"), ("index_together", "AddIndex", "DeleteIndex")): - # First, normalise them into lists of sets. - old_together = eval(old_meta.get(attr, "[]")) - new_together = eval(new_meta.get(attr, "[]")) - if old_together and isinstance(old_together[0], string_types): - old_together = [old_together] - if new_together and isinstance(new_together[0], string_types): - new_together = [new_together] - old_together = frozenset(tuple(o) for o in old_together) - new_together = frozenset(tuple(n) for n in new_together) - # See if any appeared or disappeared - disappeared = old_together.difference(new_together) - appeared = new_together.difference(old_together) - for item in disappeared: - yield (del_operation, { - "model": self.old_orm[key], - "fields": [self.old_orm[key + ":" + x] for x in item], - }) - for item in appeared: - yield (add_operation, { - "model": self.current_model_from_key(key), - "fields": [self.current_field_from_key(key, x) for x in item], - }) - - @classmethod - def is_triple(cls, triple): - "Returns whether the argument is a triple." - return isinstance(triple, (list, tuple)) and len(triple) == 3 and \ - isinstance(triple[0], string_types) and \ - isinstance(triple[1], (list, tuple)) and \ - isinstance(triple[2], dict) - - @classmethod - def different_attributes(cls, old, new): - """ - Backwards-compat comparison that ignores orm. on the RHS and not the left - and which knows django.db.models.fields.CharField = models.CharField. - Has a whole load of tests in tests/autodetection.py. - """ - - # If they're not triples, just do normal comparison - if not cls.is_triple(old) or not cls.is_triple(new): - return old != new - - # Expand them out into parts - old_field, old_pos, old_kwd = old - new_field, new_pos, new_kwd = new - - # Copy the positional and keyword arguments so we can compare them and pop off things - old_pos, new_pos = old_pos[:], new_pos[:] - old_kwd = dict(old_kwd.items()) - new_kwd = dict(new_kwd.items()) - - # Remove comparison of the existence of 'unique', that's done elsewhere. - # TODO: Make this work for custom fields where unique= means something else? - if "unique" in old_kwd: - del old_kwd['unique'] - if "unique" in new_kwd: - del new_kwd['unique'] - - # If the first bit is different, check it's not by dj.db.models... - if old_field != new_field: - if old_field.startswith("models.") and (new_field.startswith("django.db.models") \ - or new_field.startswith("django.contrib.gis")): - if old_field.split(".")[-1] != new_field.split(".")[-1]: - return True - else: - # Remove those fields from the final comparison - old_field = new_field = "" - - # If there's a positional argument in the first, and a 'to' in the second, - # see if they're actually comparable. - if (old_pos and "to" in new_kwd) and ("orm" in new_kwd['to'] and "orm" not in old_pos[0]): - # Do special comparison to fix #153 - try: - if old_pos[0] != new_kwd['to'].split("'")[1].split(".")[1]: - return True - except IndexError: - pass # Fall back to next comparison - # Remove those attrs from the final comparison - old_pos = old_pos[1:] - del new_kwd['to'] - - return old_field != new_field or old_pos != new_pos or old_kwd != new_kwd - - -class ManualChanges(BaseChanges): - """ - Detects changes by reading the command line. - """ - - def __init__(self, migrations, added_models, added_fields, added_indexes): - self.migrations = migrations - self.added_models = added_models - self.added_fields = added_fields - self.added_indexes = added_indexes - - def suggest_name(self): - bits = [] - for model_name in self.added_models: - bits.append('add_model_%s' % model_name) - for field_name in self.added_fields: - bits.append('add_field_%s' % field_name) - for index_name in self.added_indexes: - bits.append('add_index_%s' % index_name) - return '_'.join(bits).replace('.', '_') - - def get_changes(self): - # Get the model defs so we can use them for the yield later - model_defs = freeze_apps([self.migrations.app_label()]) - # Make the model changes - for model_name in self.added_models: - model = models.get_model(self.migrations.app_label(), model_name) - real_fields, meta, m2m_fields = self.split_model_def(model, model_defs[model_key(model)]) - yield ("AddModel", { - "model": model, - "model_def": real_fields, - }) - # And the field changes - for field_desc in self.added_fields: - try: - model_name, field_name = field_desc.split(".") - except (TypeError, ValueError): - raise ValueError("%r is not a valid field description." % field_desc) - model = models.get_model(self.migrations.app_label(), model_name) - real_fields, meta, m2m_fields = self.split_model_def(model, model_defs[model_key(model)]) - yield ("AddField", { - "model": model, - "field": model._meta.get_field_by_name(field_name)[0], - "field_def": real_fields[field_name], - }) - # And the indexes - for field_desc in self.added_indexes: - try: - model_name, field_name = field_desc.split(".") - except (TypeError, ValueError): - print("%r is not a valid field description." % field_desc) - model = models.get_model(self.migrations.app_label(), model_name) - yield ("AddIndex", { - "model": model, - "fields": [model._meta.get_field_by_name(field_name)[0]], - }) - - -class InitialChanges(BaseChanges): - """ - Creates all models; handles --initial. - """ - def suggest_name(self): - return 'initial' - - def __init__(self, migrations): - self.migrations = migrations - - def get_changes(self): - # Get the frozen models for this app - model_defs = freeze_apps([self.migrations.app_label()]) - - for model in models.get_models(models.get_app(self.migrations.app_label())): - - # Don't do anything for unmanaged, abstract or proxy models - if model._meta.abstract or getattr(model._meta, "proxy", False) or not getattr(model._meta, "managed", True): - continue - - real_fields, meta, m2m_fields = self.split_model_def(model, model_defs[model_key(model)]) - - # Firstly, add the main table and fields - yield ("AddModel", { - "model": model, - "model_def": real_fields, - }) - - # Then, add any indexing/uniqueness that's around - if meta: - for attr, operation in (("unique_together", "AddUnique"), ("index_together", "AddIndex")): - together = eval(meta.get(attr, "[]")) - if together: - # If it's only a single tuple, make it into the longer one - if isinstance(together[0], string_types): - together = [together] - # For each combination, make an action for it - for fields in together: - yield (operation, { - "model": model, - "fields": [model._meta.get_field_by_name(x)[0] for x in fields], - }) - - # Finally, see if there's some M2M action - for name, triple in m2m_fields.items(): - field = model._meta.get_field_by_name(name)[0] - # But only if it's not through=foo (#120) - if field.rel.through: - try: - # Django 1.1 and below - through_model = field.rel.through_model - except AttributeError: - # Django 1.2 - through_model = field.rel.through - if (not field.rel.through) or getattr(through_model._meta, "auto_created", False): - yield ("AddM2M", { - "model": model, - "field": field, - }) diff --git a/lib/python2.7/site-packages/south/creator/freezer.py b/lib/python2.7/site-packages/south/creator/freezer.py deleted file mode 100644 index 0f98cea..0000000 --- a/lib/python2.7/site-packages/south/creator/freezer.py +++ /dev/null @@ -1,192 +0,0 @@ -""" -Handles freezing of models into FakeORMs. -""" - -from __future__ import print_function - -import sys - -from django.db import models -from django.db.models.base import ModelBase, Model -from django.contrib.contenttypes.generic import GenericRelation - -from south.utils import get_attribute, auto_through -from south import modelsinspector -from south.utils.py3 import string_types - -def freeze_apps(apps): - """ - Takes a list of app labels, and returns a string of their frozen form. - """ - if isinstance(apps, string_types): - apps = [apps] - frozen_models = set() - # For each app, add in all its models - for app in apps: - for model in models.get_models(models.get_app(app)): - # Only add if it's not abstract or proxy - if not model._meta.abstract and not getattr(model._meta, "proxy", False): - frozen_models.add(model) - # Now, add all the dependencies - for model in list(frozen_models): - frozen_models.update(model_dependencies(model)) - # Serialise! - model_defs = {} - model_classes = {} - for model in frozen_models: - model_defs[model_key(model)] = prep_for_freeze(model) - model_classes[model_key(model)] = model - # Check for any custom fields that failed to freeze. - missing_fields = False - for key, fields in model_defs.items(): - for field_name, value in fields.items(): - if value is None: - missing_fields = True - model_class = model_classes[key] - field_class = model_class._meta.get_field_by_name(field_name)[0] - print(" ! Cannot freeze field '%s.%s'" % (key, field_name)) - print(" ! (this field has class %s.%s)" % (field_class.__class__.__module__, field_class.__class__.__name__)) - if missing_fields: - print("") - print(" ! South cannot introspect some fields; this is probably because they are custom") - print(" ! fields. If they worked in 0.6 or below, this is because we have removed the") - print(" ! models parser (it often broke things).") - print(" ! To fix this, read http://south.aeracode.org/wiki/MyFieldsDontWork") - sys.exit(1) - - return model_defs - -def freeze_apps_to_string(apps): - return pprint_frozen_models(freeze_apps(apps)) - -### - -def model_key(model): - "For a given model, return 'appname.modelname'." - return "%s.%s" % (model._meta.app_label, model._meta.object_name.lower()) - -def prep_for_freeze(model): - """ - Takes a model and returns the ready-to-serialise dict (all you need - to do is just pretty-print it). - """ - fields = modelsinspector.get_model_fields(model, m2m=True) - # Remove useless attributes (like 'choices') - for name, field in fields.items(): - fields[name] = remove_useless_attributes(field) - # See if there's a Meta - fields['Meta'] = remove_useless_meta(modelsinspector.get_model_meta(model)) - # Add in our own special items to track the object name and managed - fields['Meta']['object_name'] = model._meta.object_name # Special: not eval'able. - if not getattr(model._meta, "managed", True): - fields['Meta']['managed'] = repr(model._meta.managed) - return fields - -### Dependency resolvers - -def model_dependencies(model, checked_models=None): - """ - Returns a set of models this one depends on to be defined; things like - OneToOneFields as ID, ForeignKeys everywhere, etc. - """ - depends = set() - checked_models = checked_models or set() - # Get deps for each field - for field in model._meta.fields + model._meta.many_to_many: - depends.update(field_dependencies(field, checked_models)) - # Add in any non-abstract bases - for base in model.__bases__: - if issubclass(base, models.Model) and hasattr(base, '_meta') and not base._meta.abstract: - depends.add(base) - # Now recurse - new_to_check = depends - checked_models - while new_to_check: - checked_model = new_to_check.pop() - if checked_model == model or checked_model in checked_models: - continue - checked_models.add(checked_model) - deps = model_dependencies(checked_model, checked_models) - # Loop through dependencies... - for dep in deps: - # If the new dep is not already checked, add to the queue - if (dep not in depends) and (dep not in new_to_check) and (dep not in checked_models): - new_to_check.add(dep) - depends.add(dep) - return depends - -def field_dependencies(field, checked_models=None): - checked_models = checked_models or set() - depends = set() - arg_defs, kwarg_defs = modelsinspector.matching_details(field) - for attrname, options in arg_defs + list(kwarg_defs.values()): - if options.get("ignore_if_auto_through", False) and auto_through(field): - continue - if options.get("is_value", False): - value = attrname - elif attrname == 'rel.through' and hasattr(getattr(field, 'rel', None), 'through_model'): - # Hack for django 1.1 and below, where the through model is stored - # in rel.through_model while rel.through stores only the model name. - value = field.rel.through_model - else: - try: - value = get_attribute(field, attrname) - except AttributeError: - if options.get("ignore_missing", False): - continue - raise - if isinstance(value, Model): - value = value.__class__ - if not isinstance(value, ModelBase): - continue - if getattr(value._meta, "proxy", False): - value = value._meta.proxy_for_model - if value in checked_models: - continue - checked_models.add(value) - depends.add(value) - depends.update(model_dependencies(value, checked_models)) - - return depends - -### Prettyprinters - -def pprint_frozen_models(models): - return "{\n %s\n }" % ",\n ".join([ - "%r: %s" % (name, pprint_fields(fields)) - for name, fields in sorted(models.items()) - ]) - -def pprint_fields(fields): - return "{\n %s\n }" % ",\n ".join([ - "%r: %r" % (name, defn) - for name, defn in sorted(fields.items()) - ]) - -### Output sanitisers - -USELESS_KEYWORDS = ["choices", "help_text", "verbose_name"] -USELESS_DB_KEYWORDS = ["related_name", "default", "blank"] # Important for ORM, not for DB. -INDEX_KEYWORDS = ["db_index"] - -def remove_useless_attributes(field, db=False, indexes=False): - "Removes useless (for database) attributes from the field's defn." - # Work out what to remove, and remove it. - keywords = USELESS_KEYWORDS[:] - if db: - keywords += USELESS_DB_KEYWORDS[:] - if indexes: - keywords += INDEX_KEYWORDS[:] - if field: - for name in keywords: - if name in field[2]: - del field[2][name] - return field - -USELESS_META = ["verbose_name", "verbose_name_plural"] -def remove_useless_meta(meta): - "Removes useless (for database) attributes from the table's meta." - if meta: - for name in USELESS_META: - if name in meta: - del meta[name] - return meta diff --git a/lib/python2.7/site-packages/south/db/__init__.py b/lib/python2.7/site-packages/south/db/__init__.py deleted file mode 100644 index b9b7168..0000000 --- a/lib/python2.7/site-packages/south/db/__init__.py +++ /dev/null @@ -1,83 +0,0 @@ - -# Establish the common DatabaseOperations instance, which we call 'db'. -# Much thanks to cmkmrr for a lot of the code base here - -from django.conf import settings -import sys - -# A few aliases, because there's FQMNs now -engine_modules = { - 'django.db.backends.postgresql_psycopg2': 'postgresql_psycopg2', - 'django.db.backends.sqlite3': 'sqlite3', - 'django.db.backends.mysql': 'mysql', - 'mysql_oursql.standard': 'mysql', - 'django.db.backends.oracle': 'oracle', - 'sql_server.pyodbc': 'sql_server.pyodbc', #django-pyodbc-azure - 'django_pyodbc': 'sql_server.pyodbc', #django-pyodbc - 'sqlserver_ado': 'sql_server.pyodbc', #django-mssql - 'firebird': 'firebird', #django-firebird - 'django.contrib.gis.db.backends.postgis': 'postgresql_psycopg2', - 'django.contrib.gis.db.backends.spatialite': 'sqlite3', - 'django.contrib.gis.db.backends.mysql': 'mysql', - 'django.contrib.gis.db.backends.oracle': 'oracle', - 'doj.backends.zxjdbc.postgresql': 'postgresql_psycopg2', #django-jython - 'doj.backends.zxjdbc.mysql': 'mysql', #django-jython - 'doj.backends.zxjdbc.oracle': 'oracle', #django-jython -} - -# First, work out if we're multi-db or not, and which databases we have -try: - from django.db import DEFAULT_DB_ALIAS -except ImportError: - #### 1.1 or below #### - # We'll 'fake' multi-db; set the default alias - DEFAULT_DB_ALIAS = 'default' - # SOUTH_DATABASE_ADAPTER is an optional override if you have a different module - engine = getattr(settings, "SOUTH_DATABASE_ADAPTER", "south.db.%s" % settings.DATABASE_ENGINE) - # And then, we have one database with one engine - db_engines = {DEFAULT_DB_ALIAS: engine} -else: - #### 1.2 or above #### - # Loop over the defined databases, gathering up their engines - db_engines = dict([ - # Note we check to see if contrib.gis has overridden us. - (alias, "south.db.%s" % engine_modules[db_settings['ENGINE']]) - for alias, db_settings in settings.DATABASES.items() - if db_settings['ENGINE'] in engine_modules - ]) - # Update with any overrides - db_engines.update(getattr(settings, "SOUTH_DATABASE_ADAPTERS", {})) - # Check there's no None engines, or... - for alias, engine in db_engines.items(): - if engine is None: - # They've used a backend we don't support - sys.stderr.write( - ( - "There is no South database module for your database backend '%s'. " + \ - "Please either choose a supported database, check for " + \ - "SOUTH_DATABASE_ADAPTER[S] settings, " + \ - "or remove South from INSTALLED_APPS.\n" - ) % (settings.DATABASES[alias]['ENGINE'],) - ) - sys.exit(1) - -# Now, turn that into a dict of <alias: south db module> -dbs = {} -try: - for alias, module_name in db_engines.items(): - module = __import__(module_name, {}, {}, ['']) - dbs[alias] = module.DatabaseOperations(alias) -except ImportError: - # This error should only be triggered on 1.1 and below. - sys.stderr.write( - ( - "There is no South database module '%s' for your database. " + \ - "Please either choose a supported database, check for " + \ - "SOUTH_DATABASE_ADAPTER[S] settings, " + \ - "or remove South from INSTALLED_APPS.\n" - ) % (module_name,) - ) - sys.exit(1) - -# Finally, to make old migrations work, keep 'db' around as the default database -db = dbs[DEFAULT_DB_ALIAS] diff --git a/lib/python2.7/site-packages/south/db/firebird.py b/lib/python2.7/site-packages/south/db/firebird.py deleted file mode 100644 index a079819..0000000 --- a/lib/python2.7/site-packages/south/db/firebird.py +++ /dev/null @@ -1,362 +0,0 @@ -# firebird - -from __future__ import print_function - -import datetime - -from django.db import connection, models -from django.core.management.color import no_style -from django.db.utils import DatabaseError - -from south.db import generic -from south.utils.py3 import string_types - -class DatabaseOperations(generic.DatabaseOperations): - backend_name = 'firebird' - alter_string_set_type = 'ALTER %(column)s TYPE %(type)s' - alter_string_set_default = 'ALTER %(column)s SET DEFAULT %(default)s;' - alter_string_drop_null = '' - add_column_string = 'ALTER TABLE %s ADD %s;' - delete_column_string = 'ALTER TABLE %s DROP %s;' - rename_table_sql = '' - - # Features - allows_combined_alters = False - has_booleans = False - - def _fill_constraint_cache(self, db_name, table_name): - self._constraint_cache.setdefault(db_name, {}) - self._constraint_cache[db_name][table_name] = {} - - rows = self.execute(""" - SELECT - rc.RDB$CONSTRAINT_NAME, - rc.RDB$CONSTRAINT_TYPE, - cc.RDB$TRIGGER_NAME - FROM rdb$relation_constraints rc - JOIN rdb$check_constraints cc - ON rc.rdb$constraint_name = cc.rdb$constraint_name - WHERE rc.rdb$constraint_type = 'NOT NULL' - AND rc.rdb$relation_name = '%s' - """ % table_name) - - for constraint, kind, column in rows: - self._constraint_cache[db_name][table_name].setdefault(column, set()) - self._constraint_cache[db_name][table_name][column].add((kind, constraint)) - return - - def _alter_column_set_null(self, table_name, column_name, is_null): - sql = """ - UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = %(null_flag)s - WHERE RDB$FIELD_NAME = '%(column)s' - AND RDB$RELATION_NAME = '%(table_name)s' - """ - null_flag = 'NULL' if is_null else '1' - return sql % { - 'null_flag': null_flag, - 'column': column_name.upper(), - 'table_name': table_name.upper() - } - - def _column_has_default(self, params): - sql = """ - SELECT a.RDB$DEFAULT_VALUE - FROM RDB$RELATION_FIELDS a - WHERE a.RDB$FIELD_NAME = '%(column)s' - AND a.RDB$RELATION_NAME = '%(table_name)s' - """ - value = self.execute(sql % params) - return True if value else False - - - def _alter_set_defaults(self, field, name, params, sqls): - "Subcommand of alter_column that sets default values (overrideable)" - # Historically, we used to set defaults here. - # But since South 0.8, we don't ever set defaults on alter-column -- we only - # use database-level defaults as scaffolding when adding columns. - # However, we still sometimes need to remove defaults in alter-column. - if self._column_has_default(params): - sqls.append(('ALTER COLUMN %s DROP DEFAULT' % (self.quote_name(name),), [])) - - - @generic.invalidate_table_constraints - def create_table(self, table_name, fields): - columns = [] - autoinc_sql = '' - - for field_name, field in fields: - # avoid default values in CREATE TABLE statements (#925) - field._suppress_default = True - - col = self.column_sql(table_name, field_name, field) - if not col: - continue - - columns.append(col) - if isinstance(field, models.AutoField): - field_name = field.db_column or field.column - autoinc_sql = connection.ops.autoinc_sql(table_name, field_name) - - self.execute(self.create_table_sql % { - "table": self.quote_name(table_name), - "columns": ', '.join([col for col in columns if col]), - }) - - if autoinc_sql: - self.execute(autoinc_sql[0]) - self.execute(autoinc_sql[1]) - - def rename_table(self, old_table_name, table_name): - """ - Renames table is not supported by firebird. - This involve recreate all related objects (store procedure, views, triggers, etc) - """ - pass - - @generic.invalidate_table_constraints - def delete_table(self, table_name, cascade=False): - """ - Deletes the table 'table_name'. - Firebird will also delete any triggers associated with the table. - """ - super(DatabaseOperations, self).delete_table(table_name, cascade=False) - - # Also, drop sequence if exists - sql = connection.ops.drop_sequence_sql(table_name) - if sql: - try: - self.execute(sql) - except: - pass - - def column_sql(self, table_name, field_name, field, tablespace='', with_name=True, field_prepared=False): - """ - Creates the SQL snippet for a column. Used by add_column and add_table. - """ - - # If the field hasn't already been told its attribute name, do so. - if not field_prepared: - field.set_attributes_from_name(field_name) - - # hook for the field to do any resolution prior to it's attributes being queried - if hasattr(field, 'south_init'): - field.south_init() - - # Possible hook to fiddle with the fields (e.g. defaults & TEXT on MySQL) - field = self._field_sanity(field) - - try: - sql = field.db_type(connection=self._get_connection()) - except TypeError: - sql = field.db_type() - - if sql: - # Some callers, like the sqlite stuff, just want the extended type. - if with_name: - field_output = [self.quote_name(field.column), sql] - else: - field_output = [sql] - - if field.primary_key: - field_output.append('NOT NULL PRIMARY KEY') - elif field.unique: - # Just use UNIQUE (no indexes any more, we have delete_unique) - field_output.append('UNIQUE') - - sql = ' '.join(field_output) - sqlparams = () - - # if the field is "NOT NULL" and a default value is provided, create the column with it - # this allows the addition of a NOT NULL field to a table with existing rows - if not getattr(field, '_suppress_default', False): - if field.has_default(): - default = field.get_default() - # If the default is actually None, don't add a default term - if default is not None: - # If the default is a callable, then call it! - if callable(default): - default = default() - # Now do some very cheap quoting. TODO: Redesign return values to avoid this. - if isinstance(default, string_types): - default = "'%s'" % default.replace("'", "''") - elif isinstance(default, (datetime.date, datetime.time, datetime.datetime)): - default = "'%s'" % default - elif isinstance(default, bool): - default = int(default) - # Escape any % signs in the output (bug #317) - if isinstance(default, string_types): - default = default.replace("%", "%%") - # Add it in - sql += " DEFAULT %s" - sqlparams = (default) - elif (not field.null and field.blank) or (field.get_default() == ''): - if field.empty_strings_allowed and self._get_connection().features.interprets_empty_strings_as_nulls: - sql += " DEFAULT ''" - # Error here would be nice, but doesn't seem to play fair. - #else: - # raise ValueError("Attempting to add a non null column that isn't character based without an explicit default value.") - - # Firebird need set not null after of default value keyword - if not field.primary_key and not field.null: - sql += ' NOT NULL' - - if field.rel and self.supports_foreign_keys: - self.add_deferred_sql( - self.foreign_key_sql( - table_name, - field.column, - field.rel.to._meta.db_table, - field.rel.to._meta.get_field(field.rel.field_name).column - ) - ) - - # Things like the contrib.gis module fields have this in 1.1 and below - if hasattr(field, 'post_create_sql'): - for stmt in field.post_create_sql(no_style(), table_name): - self.add_deferred_sql(stmt) - - # Avoid double index creation (#1317) - # Firebird creates an index implicity for each foreign key field - # sql_indexes_for_field tries to create an index for that field too - if not field.rel: - # In 1.2 and above, you have to ask the DatabaseCreation stuff for it. - # This also creates normal indexes in 1.1. - if hasattr(self._get_connection().creation, "sql_indexes_for_field"): - # Make a fake model to pass in, with only db_table - model = self.mock_model("FakeModelForGISCreation", table_name) - for stmt in self._get_connection().creation.sql_indexes_for_field(model, field, no_style()): - self.add_deferred_sql(stmt) - - if sql: - return sql % sqlparams - else: - return None - - - def _drop_constraints(self, table_name, name, field): - if self.has_check_constraints: - check_constraints = self._constraints_affecting_columns(table_name, [name], "CHECK") - for constraint in check_constraints: - self.execute(self.delete_check_sql % { - 'table': self.quote_name(table_name), - 'constraint': self.quote_name(constraint), - }) - - # Drop or add UNIQUE constraint - unique_constraint = list(self._constraints_affecting_columns(table_name, [name], "UNIQUE")) - if field.unique and not unique_constraint: - self.create_unique(table_name, [name]) - elif not field.unique and unique_constraint: - self.delete_unique(table_name, [name]) - - # Drop all foreign key constraints - try: - self.delete_foreign_key(table_name, name) - except ValueError: - # There weren't any - pass - - - @generic.invalidate_table_constraints - def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False): - """ - Alters the given column name so it will match the given field. - Note that conversion between the two by the database must be possible. - Will not automatically add _id by default; to have this behavour, pass - explicit_name=False. - - @param table_name: The name of the table to add the column to - @param name: The name of the column to alter - @param field: The new field definition to use - """ - - if self.dry_run: - if self.debug: - print(' - no dry run output for alter_column() due to dynamic DDL, sorry') - return - - - # hook for the field to do any resolution prior to it's attributes being queried - if hasattr(field, 'south_init'): - field.south_init() - - # Add _id or whatever if we need to - field.set_attributes_from_name(name) - if not explicit_name: - name = field.column - else: - field.column = name - - if not ignore_constraints: - # Drop all check constraints. Note that constraints will be added back - # with self.alter_string_set_type and self.alter_string_drop_null. - self._drop_constraints(table_name, name, field) - - # First, change the type - params = { - "column": self.quote_name(name), - "type": self._db_type_for_alter_column(field), - "table_name": table_name - } - - # SQLs is a list of (SQL, values) pairs. - sqls = [] - sqls_extra = [] - - # Only alter the column if it has a type (Geometry ones sometimes don't) - if params["type"] is not None: - sqls.append((self.alter_string_set_type % params, [])) - - # Add any field- and backend- specific modifications - self._alter_add_column_mods(field, name, params, sqls) - - # Next, nullity: modified, firebird doesn't support DROP NOT NULL - sqls_extra.append(self._alter_column_set_null(table_name, name, field.null)) - - # Next, set any default - self._alter_set_defaults(field, name, params, sqls) - - # Finally, actually change the column - if self.allows_combined_alters: - sqls, values = list(zip(*sqls)) - self.execute( - "ALTER TABLE %s %s;" % (self.quote_name(table_name), ", ".join(sqls)), - generic.flatten(values), - ) - else: - # Databases like e.g. MySQL don't like more than one alter at once. - for sql, values in sqls: - try: - self.execute("ALTER TABLE %s %s;" % (self.quote_name(table_name), sql), values) - except DatabaseError as e: - print(e) - - - # Execute extra sql, which don't need ALTER TABLE statement - for sql in sqls_extra: - self.execute(sql) - - if not ignore_constraints: - # Add back FK constraints if needed - if field.rel and self.supports_foreign_keys: - self.execute( - self.foreign_key_sql( - table_name, - field.column, - field.rel.to._meta.db_table, - field.rel.to._meta.get_field(field.rel.field_name).column - ) - ) - - @generic.copy_column_constraints - @generic.delete_column_constraints - def rename_column(self, table_name, old, new): - if old == new: - # Short-circuit out - return [] - - self.execute('ALTER TABLE %s ALTER %s TO %s;' % ( - self.quote_name(table_name), - self.quote_name(old), - self.quote_name(new), - )) diff --git a/lib/python2.7/site-packages/south/db/generic.py b/lib/python2.7/site-packages/south/db/generic.py deleted file mode 100644 index 5c19354..0000000 --- a/lib/python2.7/site-packages/south/db/generic.py +++ /dev/null @@ -1,1164 +0,0 @@ -from __future__ import print_function - -import re -import sys - -from django.core.management.color import no_style -from django.db import transaction, models -from django.db.utils import DatabaseError -from django.db.backends.util import truncate_name -from django.db.backends.creation import BaseDatabaseCreation -from django.db.models.fields import NOT_PROVIDED -from django.dispatch import dispatcher -from django.conf import settings -from django.utils.datastructures import SortedDict -try: - from django.utils.functional import cached_property -except ImportError: - class cached_property(object): - """ - Decorator that creates converts a method with a single - self argument into a property cached on the instance. - """ - def __init__(self, func): - self.func = func - - def __get__(self, instance, type): - res = instance.__dict__[self.func.__name__] = self.func(instance) - return res - -from south.logger import get_logger -from south.utils.py3 import string_types, text_type - - -def alias(attrname): - """ - Returns a function which calls 'attrname' - for function aliasing. - We can't just use foo = bar, as this breaks subclassing. - """ - def func(self, *args, **kwds): - return getattr(self, attrname)(*args, **kwds) - return func - - -def invalidate_table_constraints(func): - def _cache_clear(self, table, *args, **opts): - self._set_cache(table, value=INVALID) - return func(self, table, *args, **opts) - return _cache_clear - - -def delete_column_constraints(func): - def _column_rm(self, table, column, *args, **opts): - self._set_cache(table, column, value=[]) - return func(self, table, column, *args, **opts) - return _column_rm - - -def copy_column_constraints(func): - def _column_cp(self, table, column_old, column_new, *args, **opts): - db_name = self._get_setting('NAME') - self._set_cache(table, column_new, value=self.lookup_constraint(db_name, table, column_old)) - return func(self, table, column_old, column_new, *args, **opts) - return _column_cp - - -class INVALID(Exception): - def __repr__(self): - return 'INVALID' - - -class DryRunError(ValueError): - pass - - -class DatabaseOperations(object): - """ - Generic SQL implementation of the DatabaseOperations. - Some of this code comes from Django Evolution. - """ - - alter_string_set_type = 'ALTER COLUMN %(column)s TYPE %(type)s' - alter_string_set_null = 'ALTER COLUMN %(column)s DROP NOT NULL' - alter_string_drop_null = 'ALTER COLUMN %(column)s SET NOT NULL' - delete_check_sql = 'ALTER TABLE %(table)s DROP CONSTRAINT %(constraint)s' - add_column_string = 'ALTER TABLE %s ADD COLUMN %s;' - delete_unique_sql = "ALTER TABLE %s DROP CONSTRAINT %s" - delete_foreign_key_sql = 'ALTER TABLE %(table)s DROP CONSTRAINT %(constraint)s' - create_table_sql = 'CREATE TABLE %(table)s (%(columns)s)' - max_index_name_length = 63 - drop_index_string = 'DROP INDEX %(index_name)s' - delete_column_string = 'ALTER TABLE %s DROP COLUMN %s CASCADE;' - create_primary_key_string = "ALTER TABLE %(table)s ADD CONSTRAINT %(constraint)s PRIMARY KEY (%(columns)s)" - delete_primary_key_sql = "ALTER TABLE %(table)s DROP CONSTRAINT %(constraint)s" - add_check_constraint_fragment = "ADD CONSTRAINT %(constraint)s CHECK (%(check)s)" - rename_table_sql = "ALTER TABLE %s RENAME TO %s;" - backend_name = None - default_schema_name = "public" - - # Features - allows_combined_alters = True - supports_foreign_keys = True - has_check_constraints = True - has_booleans = True - raises_default_errors = True - - @cached_property - def has_ddl_transactions(self): - """ - Tests the database using feature detection to see if it has - transactional DDL support. - """ - self._possibly_initialise() - connection = self._get_connection() - if hasattr(connection.features, "confirm") and not connection.features._confirmed: - connection.features.confirm() - # Django 1.3's MySQLdb backend doesn't raise DatabaseError - exceptions = (DatabaseError, ) - try: - from MySQLdb import OperationalError - exceptions += (OperationalError, ) - except ImportError: - pass - # Now do the test - if getattr(connection.features, 'supports_transactions', True): - cursor = connection.cursor() - self.start_transaction() - cursor.execute('CREATE TABLE DDL_TRANSACTION_TEST (X INT)') - self.rollback_transaction() - try: - try: - cursor.execute('CREATE TABLE DDL_TRANSACTION_TEST (X INT)') - except exceptions: - return False - else: - return True - finally: - cursor.execute('DROP TABLE DDL_TRANSACTION_TEST') - else: - return False - - def __init__(self, db_alias): - self.debug = False - self.deferred_sql = [] - self.dry_run = False - self.pending_transactions = 0 - self.pending_create_signals = [] - self.db_alias = db_alias - self._constraint_cache = {} - self._initialised = False - - def lookup_constraint(self, db_name, table_name, column_name=None): - """ return a set() of constraints for db_name.table_name.column_name """ - def _lookup(): - table = self._constraint_cache[db_name][table_name] - if table is INVALID: - raise INVALID - elif column_name is None: - return list(table.items()) - else: - return table[column_name] - - try: - ret = _lookup() - return ret - except INVALID: - del self._constraint_cache[db_name][table_name] - self._fill_constraint_cache(db_name, table_name) - except KeyError: - if self._is_valid_cache(db_name, table_name): - return [] - self._fill_constraint_cache(db_name, table_name) - - return self.lookup_constraint(db_name, table_name, column_name) - - def _set_cache(self, table_name, column_name=None, value=INVALID): - db_name = self._get_setting('NAME') - try: - if column_name is not None: - self._constraint_cache[db_name][table_name][column_name] = value - else: - self._constraint_cache[db_name][table_name] = value - except (LookupError, TypeError): - pass - - def _is_valid_cache(self, db_name, table_name): - # we cache per-table so if the table is there it is valid - try: - return self._constraint_cache[db_name][table_name] is not INVALID - except KeyError: - return False - - def _is_multidb(self): - try: - from django.db import connections - connections # Prevents "unused import" warning - except ImportError: - return False - else: - return True - - def _get_connection(self): - """ - Returns a django connection for a given DB Alias - """ - if self._is_multidb(): - from django.db import connections - return connections[self.db_alias] - else: - from django.db import connection - return connection - - def _get_setting(self, setting_name): - """ - Allows code to get a setting (like, for example, STORAGE_ENGINE) - """ - setting_name = setting_name.upper() - connection = self._get_connection() - if self._is_multidb(): - # Django 1.2 and above - return connection.settings_dict[setting_name] - else: - # Django 1.1 and below - return getattr(settings, "DATABASE_%s" % setting_name) - - def _has_setting(self, setting_name): - """ - Existence-checking version of _get_setting. - """ - try: - self._get_setting(setting_name) - except (KeyError, AttributeError): - return False - else: - return True - - def _get_schema_name(self): - try: - return self._get_setting('schema') - except (KeyError, AttributeError): - return self.default_schema_name - - def _possibly_initialise(self): - if not self._initialised: - self.connection_init() - self._initialised = True - - def connection_init(self): - """ - Run before any SQL to let database-specific config be sent as a command, - e.g. which storage engine (MySQL) or transaction serialisability level. - """ - pass - - def quote_name(self, name): - """ - Uses the database backend to quote the given table/column name. - """ - return self._get_connection().ops.quote_name(name) - - def _print_sql_error(self, e, sql, params=[]): - print('FATAL ERROR - The following SQL query failed: %s' % sql, file=sys.stderr) - print('The error was: %s' % e, file=sys.stderr) - - def execute(self, sql, params=[], print_all_errors=True): - """ - Executes the given SQL statement, with optional parameters. - If the instance's debug attribute is True, prints out what it executes. - """ - - self._possibly_initialise() - - cursor = self._get_connection().cursor() - if self.debug: - print(" = %s" % sql, params) - - if self.dry_run: - return [] - - get_logger().debug(text_type('execute "%s" with params "%s"' % (sql, params))) - - try: - cursor.execute(sql, params) - except DatabaseError as e: - if print_all_errors: - self._print_sql_error(e, sql, params) - raise - - try: - return cursor.fetchall() - except: - return [] - - def execute_many(self, sql, regex=r"(?mx) ([^';]* (?:'[^']*'[^';]*)*)", comment_regex=r"(?mx) (?:^\s*$)|(?:--.*$)"): - """ - Takes a SQL file and executes it as many separate statements. - (Some backends, such as Postgres, don't work otherwise.) - """ - # Be warned: This function is full of dark magic. Make sure you really - # know regexes before trying to edit it. - # First, strip comments - sql = "\n".join([x.strip().replace("%", "%%") for x in re.split(comment_regex, sql) if x.strip()]) - # Now execute each statement - for st in re.split(regex, sql)[1:][::2]: - self.execute(st) - - def add_deferred_sql(self, sql): - """ - Add a SQL statement to the deferred list, that won't be executed until - this instance's execute_deferred_sql method is run. - """ - self.deferred_sql.append(sql) - - def execute_deferred_sql(self): - """ - Executes all deferred SQL, resetting the deferred_sql list - """ - for sql in self.deferred_sql: - self.execute(sql) - - self.deferred_sql = [] - - def clear_deferred_sql(self): - """ - Resets the deferred_sql list to empty. - """ - self.deferred_sql = [] - - def clear_run_data(self, pending_creates = None): - """ - Resets variables to how they should be before a run. Used for dry runs. - If you want, pass in an old panding_creates to reset to. - """ - self.clear_deferred_sql() - self.pending_create_signals = pending_creates or [] - - def get_pending_creates(self): - return self.pending_create_signals - - @invalidate_table_constraints - def create_table(self, table_name, fields): - """ - Creates the table 'table_name'. 'fields' is a tuple of fields, - each repsented by a 2-part tuple of field name and a - django.db.models.fields.Field object - """ - - if len(table_name) > 63: - print(" ! WARNING: You have a table name longer than 63 characters; this will not fully work on PostgreSQL or MySQL.") - - # avoid default values in CREATE TABLE statements (#925) - for field_name, field in fields: - field._suppress_default = True - - columns = [ - self.column_sql(table_name, field_name, field) - for field_name, field in fields - ] - - self.execute(self.create_table_sql % { - "table": self.quote_name(table_name), - "columns": ', '.join([col for col in columns if col]), - }) - - add_table = alias('create_table') # Alias for consistency's sake - - @invalidate_table_constraints - def rename_table(self, old_table_name, table_name): - """ - Renames the table 'old_table_name' to 'table_name'. - """ - if old_table_name == table_name: - # Short-circuit out. - return - params = (self.quote_name(old_table_name), self.quote_name(table_name)) - self.execute(self.rename_table_sql % params) - # Invalidate the not-yet-indexed table - self._set_cache(table_name, value=INVALID) - - @invalidate_table_constraints - def delete_table(self, table_name, cascade=True): - """ - Deletes the table 'table_name'. - """ - params = (self.quote_name(table_name), ) - if cascade: - self.execute('DROP TABLE %s CASCADE;' % params) - else: - self.execute('DROP TABLE %s;' % params) - - drop_table = alias('delete_table') - - @invalidate_table_constraints - def clear_table(self, table_name): - """ - Deletes all rows from 'table_name'. - """ - params = (self.quote_name(table_name), ) - self.execute('DELETE FROM %s;' % params) - - @invalidate_table_constraints - def add_column(self, table_name, name, field, keep_default=True): - """ - Adds the column 'name' to the table 'table_name'. - Uses the 'field' paramater, a django.db.models.fields.Field instance, - to generate the necessary sql - - @param table_name: The name of the table to add the column to - @param name: The name of the column to add - @param field: The field to use - """ - sql = self.column_sql(table_name, name, field) - if sql: - params = ( - self.quote_name(table_name), - sql, - ) - sql = self.add_column_string % params - self.execute(sql) - - # Now, drop the default if we need to - if field.default is not None: - field.default = NOT_PROVIDED - self.alter_column(table_name, name, field, explicit_name=False, ignore_constraints=True) - - def _db_type_for_alter_column(self, field): - """ - Returns a field's type suitable for ALTER COLUMN. - By default it just returns field.db_type(). - To be overriden by backend specific subclasses - @param field: The field to generate type for - """ - try: - return field.db_type(connection=self._get_connection()) - except TypeError: - return field.db_type() - - def _alter_add_column_mods(self, field, name, params, sqls): - """ - Subcommand of alter_column that modifies column definitions beyond - the type string -- e.g. adding constraints where they cannot be specified - as part of the type (overrideable) - """ - pass - - def _alter_set_defaults(self, field, name, params, sqls): - "Subcommand of alter_column that sets default values (overrideable)" - # Historically, we used to set defaults here. - # But since South 0.8, we don't ever set defaults on alter-column -- we only - # use database-level defaults as scaffolding when adding columns. - # However, we still sometimes need to remove defaults in alter-column. - sqls.append(('ALTER COLUMN %s DROP DEFAULT' % (self.quote_name(name),), [])) - - def _update_nulls_to_default(self, params, field): - "Subcommand of alter_column that updates nulls to default value (overrideable)" - default = field.get_db_prep_save(field.get_default(), connection=self._get_connection()) - self.execute('UPDATE %(table_name)s SET %(column)s=%%s WHERE %(column)s IS NULL' % params, [default]) - - @invalidate_table_constraints - def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False): - """ - Alters the given column name so it will match the given field. - Note that conversion between the two by the database must be possible. - Will not automatically add _id by default; to have this behavour, pass - explicit_name=False. - - @param table_name: The name of the table to add the column to - @param name: The name of the column to alter - @param field: The new field definition to use - """ - - if self.dry_run: - if self.debug: - print(' - no dry run output for alter_column() due to dynamic DDL, sorry') - return - - # hook for the field to do any resolution prior to it's attributes being queried - if hasattr(field, 'south_init'): - field.south_init() - - # Add _id or whatever if we need to - field.set_attributes_from_name(name) - if not explicit_name: - name = field.column - else: - field.column = name - - if not ignore_constraints: - # Drop all check constraints. Note that constraints will be added back - # with self.alter_string_set_type and self.alter_string_drop_null. - if self.has_check_constraints: - check_constraints = self._constraints_affecting_columns(table_name, [name], "CHECK") - for constraint in check_constraints: - self.execute(self.delete_check_sql % { - 'table': self.quote_name(table_name), - 'constraint': self.quote_name(constraint), - }) - - # Drop all foreign key constraints - try: - self.delete_foreign_key(table_name, name) - except ValueError: - # There weren't any - pass - - # First, change the type - params = { - "column": self.quote_name(name), - "type": self._db_type_for_alter_column(field), - "table_name": self.quote_name(table_name) - } - - # SQLs is a list of (SQL, values) pairs. - sqls = [] - - # Only alter the column if it has a type (Geometry ones sometimes don't) - if params["type"] is not None: - sqls.append((self.alter_string_set_type % params, [])) - - # Add any field- and backend- specific modifications - self._alter_add_column_mods(field, name, params, sqls) - # Next, nullity - if field.null or field.has_default(): - sqls.append((self.alter_string_set_null % params, [])) - else: - sqls.append((self.alter_string_drop_null % params, [])) - - # Do defaults - self._alter_set_defaults(field, name, params, sqls) - - # Actually change the column (step 1 -- Nullity may need to be fixed) - if self.allows_combined_alters: - sqls, values = zip(*sqls) - self.execute( - "ALTER TABLE %s %s;" % (self.quote_name(table_name), ", ".join(sqls)), - flatten(values), - ) - else: - # Databases like e.g. MySQL don't like more than one alter at once. - for sql, values in sqls: - self.execute("ALTER TABLE %s %s;" % (self.quote_name(table_name), sql), values) - - if not field.null and field.has_default(): - # Final fixes - self._update_nulls_to_default(params, field) - self.execute("ALTER TABLE %s %s;" % (self.quote_name(table_name), self.alter_string_drop_null % params), []) - - if not ignore_constraints: - # Add back FK constraints if needed - if field.rel and self.supports_foreign_keys: - self.execute( - self.foreign_key_sql( - table_name, - field.column, - field.rel.to._meta.db_table, - field.rel.to._meta.get_field(field.rel.field_name).column - ) - ) - - def _fill_constraint_cache(self, db_name, table_name): - - schema = self._get_schema_name() - ifsc_tables = ["constraint_column_usage", "key_column_usage"] - - self._constraint_cache.setdefault(db_name, {}) - self._constraint_cache[db_name][table_name] = {} - - for ifsc_table in ifsc_tables: - rows = self.execute(""" - SELECT kc.constraint_name, kc.column_name, c.constraint_type - FROM information_schema.%s AS kc - JOIN information_schema.table_constraints AS c ON - kc.table_schema = c.table_schema AND - kc.table_name = c.table_name AND - kc.constraint_name = c.constraint_name - WHERE - kc.table_schema = %%s AND - kc.table_name = %%s - """ % ifsc_table, [schema, table_name]) - for constraint, column, kind in rows: - self._constraint_cache[db_name][table_name].setdefault(column, set()) - self._constraint_cache[db_name][table_name][column].add((kind, constraint)) - return - - def _constraints_affecting_columns(self, table_name, columns, type="UNIQUE"): - """ - Gets the names of the constraints affecting the given columns. - If columns is None, returns all constraints of the type on the table. - """ - if self.dry_run: - raise DryRunError("Cannot get constraints for columns.") - - if columns is not None: - columns = set(map(lambda s: s.lower(), columns)) - - db_name = self._get_setting('NAME') - - cnames = {} - for col, constraints in self.lookup_constraint(db_name, table_name): - for kind, cname in constraints: - if kind == type: - cnames.setdefault(cname, set()) - cnames[cname].add(col.lower()) - - for cname, cols in cnames.items(): - if cols == columns or columns is None: - yield cname - - @invalidate_table_constraints - def create_unique(self, table_name, columns): - """ - Creates a UNIQUE constraint on the columns on the given table. - """ - - if not isinstance(columns, (list, tuple)): - columns = [columns] - - name = self.create_index_name(table_name, columns, suffix="_uniq") - - cols = ", ".join(map(self.quote_name, columns)) - self.execute("ALTER TABLE %s ADD CONSTRAINT %s UNIQUE (%s)" % ( - self.quote_name(table_name), - self.quote_name(name), - cols, - )) - return name - - @invalidate_table_constraints - def delete_unique(self, table_name, columns): - """ - Deletes a UNIQUE constraint on precisely the columns on the given table. - """ - - if not isinstance(columns, (list, tuple)): - columns = [columns] - - # Dry runs mean we can't do anything. - if self.dry_run: - if self.debug: - print(' - no dry run output for delete_unique_column() due to dynamic DDL, sorry') - return - - constraints = list(self._constraints_affecting_columns(table_name, columns)) - if not constraints: - raise ValueError("Cannot find a UNIQUE constraint on table %s, columns %r" % (table_name, columns)) - for constraint in constraints: - self.execute(self.delete_unique_sql % ( - self.quote_name(table_name), - self.quote_name(constraint), - )) - - def column_sql(self, table_name, field_name, field, tablespace='', with_name=True, field_prepared=False): - """ - Creates the SQL snippet for a column. Used by add_column and add_table. - """ - - # If the field hasn't already been told its attribute name, do so. - if not field_prepared: - field.set_attributes_from_name(field_name) - - # hook for the field to do any resolution prior to it's attributes being queried - if hasattr(field, 'south_init'): - field.south_init() - - # Possible hook to fiddle with the fields (e.g. defaults & TEXT on MySQL) - field = self._field_sanity(field) - - try: - sql = field.db_type(connection=self._get_connection()) - except TypeError: - sql = field.db_type() - - if sql: - - # Some callers, like the sqlite stuff, just want the extended type. - if with_name: - field_output = [self.quote_name(field.column), sql] - else: - field_output = [sql] - - field_output.append('%sNULL' % (not field.null and 'NOT ' or '')) - if field.primary_key: - field_output.append('PRIMARY KEY') - elif field.unique: - # Just use UNIQUE (no indexes any more, we have delete_unique) - field_output.append('UNIQUE') - - tablespace = field.db_tablespace or tablespace - if tablespace and getattr(self._get_connection().features, "supports_tablespaces", False) and field.unique: - # We must specify the index tablespace inline, because we - # won't be generating a CREATE INDEX statement for this field. - field_output.append(self._get_connection().ops.tablespace_sql(tablespace, inline=True)) - - sql = ' '.join(field_output) - sqlparams = () - # if the field is "NOT NULL" and a default value is provided, create the column with it - # this allows the addition of a NOT NULL field to a table with existing rows - if not getattr(field, '_suppress_default', False): - if field.has_default(): - default = field.get_default() - # If the default is actually None, don't add a default term - if default is not None: - # If the default is a callable, then call it! - if callable(default): - default = default() - - default = field.get_db_prep_save(default, connection=self._get_connection()) - default = self._default_value_workaround(default) - # Now do some very cheap quoting. TODO: Redesign return values to avoid this. - if isinstance(default, string_types): - default = "'%s'" % default.replace("'", "''") - # Escape any % signs in the output (bug #317) - if isinstance(default, string_types): - default = default.replace("%", "%%") - # Add it in - sql += " DEFAULT %s" - sqlparams = (default) - elif (not field.null and field.blank) or (field.get_default() == ''): - if field.empty_strings_allowed and self._get_connection().features.interprets_empty_strings_as_nulls: - sql += " DEFAULT ''" - # Error here would be nice, but doesn't seem to play fair. - #else: - # raise ValueError("Attempting to add a non null column that isn't character based without an explicit default value.") - - if field.rel and self.supports_foreign_keys: - self.add_deferred_sql( - self.foreign_key_sql( - table_name, - field.column, - field.rel.to._meta.db_table, - field.rel.to._meta.get_field(field.rel.field_name).column - ) - ) - - # Things like the contrib.gis module fields have this in 1.1 and below - if hasattr(field, 'post_create_sql'): - for stmt in field.post_create_sql(no_style(), table_name): - self.add_deferred_sql(stmt) - - # In 1.2 and above, you have to ask the DatabaseCreation stuff for it. - # This also creates normal indexes in 1.1. - if hasattr(self._get_connection().creation, "sql_indexes_for_field"): - # Make a fake model to pass in, with only db_table - model = self.mock_model("FakeModelForGISCreation", table_name) - for stmt in self._get_connection().creation.sql_indexes_for_field(model, field, no_style()): - self.add_deferred_sql(stmt) - - if sql: - return sql % sqlparams - else: - return None - - def _field_sanity(self, field): - """ - Placeholder for DBMS-specific field alterations (some combos aren't valid, - e.g. DEFAULT and TEXT on MySQL) - """ - return field - - def _default_value_workaround(self, value): - """ - DBMS-specific value alterations (this really works around - missing functionality in Django backends) - """ - if isinstance(value, bool) and not self.has_booleans: - return int(value) - else: - return value - - def foreign_key_sql(self, from_table_name, from_column_name, to_table_name, to_column_name): - """ - Generates a full SQL statement to add a foreign key constraint - """ - constraint_name = '%s_refs_%s_%s' % (from_column_name, to_column_name, self._digest(from_table_name, to_table_name)) - return 'ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % ( - self.quote_name(from_table_name), - self.quote_name(self.shorten_name(constraint_name)), - self.quote_name(from_column_name), - self.quote_name(to_table_name), - self.quote_name(to_column_name), - self._get_connection().ops.deferrable_sql() # Django knows this - ) - - @invalidate_table_constraints - def delete_foreign_key(self, table_name, column): - """ - Drop a foreign key constraint - """ - if self.dry_run: - if self.debug: - print(' - no dry run output for delete_foreign_key() due to dynamic DDL, sorry') - return # We can't look at the DB to get the constraints - constraints = self._find_foreign_constraints(table_name, column) - if not constraints: - raise ValueError("Cannot find a FOREIGN KEY constraint on table %s, column %s" % (table_name, column)) - for constraint_name in constraints: - self.execute(self.delete_foreign_key_sql % { - "table": self.quote_name(table_name), - "constraint": self.quote_name(constraint_name), - }) - - drop_foreign_key = alias('delete_foreign_key') - - def _find_foreign_constraints(self, table_name, column_name=None): - constraints = self._constraints_affecting_columns( - table_name, [column_name], "FOREIGN KEY") - - primary_key_columns = self._find_primary_key_columns(table_name) - - if len(primary_key_columns) > 1: - # Composite primary keys cannot be referenced by a foreign key - return list(constraints) - else: - primary_key_columns.add(column_name) - recursive_constraints = set(self._constraints_affecting_columns( - table_name, primary_key_columns, "FOREIGN KEY")) - return list(recursive_constraints.union(constraints)) - - def _digest(self, *args): - """ - Use django.db.backends.creation.BaseDatabaseCreation._digest - to create index name in Django style. An evil hack :( - """ - if not hasattr(self, '_django_db_creation'): - self._django_db_creation = BaseDatabaseCreation(self._get_connection()) - return self._django_db_creation._digest(*args) - - def shorten_name(self, name): - return truncate_name(name, self._get_connection().ops.max_name_length()) - - def create_index_name(self, table_name, column_names, suffix=""): - """ - Generate a unique name for the index - """ - - # If there is just one column in the index, use a default algorithm from Django - if len(column_names) == 1 and not suffix: - try: - _hash = self._digest([column_names[0]]) - except TypeError: - # Django < 1.5 backward compatibility. - _hash = self._digest(column_names[0]) - return self.shorten_name( - '%s_%s' % (table_name, _hash), - ) - - # Else generate the name for the index by South - table_name = table_name.replace('"', '').replace('.', '_') - index_unique_name = '_%x' % abs(hash((table_name, ','.join(column_names)))) - - # If the index name is too long, truncate it - index_name = ('%s_%s%s%s' % (table_name, column_names[0], index_unique_name, suffix)).replace('"', '').replace('.', '_') - if len(index_name) > self.max_index_name_length: - part = ('_%s%s%s' % (column_names[0], index_unique_name, suffix)) - index_name = '%s%s' % (table_name[:(self.max_index_name_length - len(part))], part) - - return index_name - - def create_index_sql(self, table_name, column_names, unique=False, db_tablespace=''): - """ - Generates a create index statement on 'table_name' for a list of 'column_names' - """ - if not column_names: - print("No column names supplied on which to create an index") - return '' - - connection = self._get_connection() - if db_tablespace and connection.features.supports_tablespaces: - tablespace_sql = ' ' + connection.ops.tablespace_sql(db_tablespace) - else: - tablespace_sql = '' - - index_name = self.create_index_name(table_name, column_names) - return 'CREATE %sINDEX %s ON %s (%s)%s;' % ( - unique and 'UNIQUE ' or '', - self.quote_name(index_name), - self.quote_name(table_name), - ','.join([self.quote_name(field) for field in column_names]), - tablespace_sql - ) - - @invalidate_table_constraints - def create_index(self, table_name, column_names, unique=False, db_tablespace=''): - """ Executes a create index statement """ - sql = self.create_index_sql(table_name, column_names, unique, db_tablespace) - self.execute(sql) - - @invalidate_table_constraints - def delete_index(self, table_name, column_names, db_tablespace=''): - """ - Deletes an index created with create_index. - This is possible using only columns due to the deterministic - index naming function which relies on column names. - """ - if isinstance(column_names, string_types): - column_names = [column_names] - name = self.create_index_name(table_name, column_names) - sql = self.drop_index_string % { - "index_name": self.quote_name(name), - "table_name": self.quote_name(table_name), - } - self.execute(sql) - - drop_index = alias('delete_index') - - @delete_column_constraints - def delete_column(self, table_name, name): - """ - Deletes the column 'column_name' from the table 'table_name'. - """ - params = (self.quote_name(table_name), self.quote_name(name)) - self.execute(self.delete_column_string % params, []) - - drop_column = alias('delete_column') - - def rename_column(self, table_name, old, new): - """ - Renames the column 'old' from the table 'table_name' to 'new'. - """ - raise NotImplementedError("rename_column has no generic SQL syntax") - - @invalidate_table_constraints - def delete_primary_key(self, table_name): - """ - Drops the old primary key. - """ - # Dry runs mean we can't do anything. - if self.dry_run: - if self.debug: - print(' - no dry run output for delete_primary_key() due to dynamic DDL, sorry') - return - - constraints = list(self._constraints_affecting_columns(table_name, None, type="PRIMARY KEY")) - if not constraints: - raise ValueError("Cannot find a PRIMARY KEY constraint on table %s" % (table_name,)) - - for constraint in constraints: - self.execute(self.delete_primary_key_sql % { - "table": self.quote_name(table_name), - "constraint": self.quote_name(constraint), - }) - - drop_primary_key = alias('delete_primary_key') - - @invalidate_table_constraints - def create_primary_key(self, table_name, columns): - """ - Creates a new primary key on the specified columns. - """ - if not isinstance(columns, (list, tuple)): - columns = [columns] - self.execute(self.create_primary_key_string % { - "table": self.quote_name(table_name), - "constraint": self.quote_name(table_name + "_pkey"), - "columns": ", ".join(map(self.quote_name, columns)), - }) - - def _find_primary_key_columns(self, table_name): - """ - Find all columns of the primary key of the specified table - """ - db_name = self._get_setting('NAME') - - primary_key_columns = set() - for col, constraints in self.lookup_constraint(db_name, table_name): - for kind, cname in constraints: - if kind == 'PRIMARY KEY': - primary_key_columns.add(col.lower()) - - return primary_key_columns - - def start_transaction(self): - """ - Makes sure the following commands are inside a transaction. - Must be followed by a (commit|rollback)_transaction call. - """ - if self.dry_run: - self.pending_transactions += 1 - transaction.commit_unless_managed(using=self.db_alias) - transaction.enter_transaction_management(using=self.db_alias) - transaction.managed(True, using=self.db_alias) - - def commit_transaction(self): - """ - Commits the current transaction. - Must be preceded by a start_transaction call. - """ - if self.dry_run: - return - transaction.commit(using=self.db_alias) - transaction.leave_transaction_management(using=self.db_alias) - - def rollback_transaction(self): - """ - Rolls back the current transaction. - Must be preceded by a start_transaction call. - """ - if self.dry_run: - self.pending_transactions -= 1 - transaction.rollback(using=self.db_alias) - transaction.leave_transaction_management(using=self.db_alias) - - def rollback_transactions_dry_run(self): - """ - Rolls back all pending_transactions during this dry run. - """ - if not self.dry_run: - return - while self.pending_transactions > 0: - self.rollback_transaction() - if transaction.is_dirty(using=self.db_alias): - # Force an exception, if we're still in a dirty transaction. - # This means we are missing a COMMIT/ROLLBACK. - transaction.leave_transaction_management(using=self.db_alias) - - def send_create_signal(self, app_label, model_names): - self.pending_create_signals.append((app_label, model_names)) - - def send_pending_create_signals(self, verbosity=0, interactive=False): - # Group app_labels together - signals = SortedDict() - for (app_label, model_names) in self.pending_create_signals: - try: - signals[app_label].extend(model_names) - except KeyError: - signals[app_label] = list(model_names) - # Send only one signal per app. - for (app_label, model_names) in signals.items(): - self.really_send_create_signal(app_label, list(set(model_names)), - verbosity=verbosity, - interactive=interactive) - self.pending_create_signals = [] - - def really_send_create_signal(self, app_label, model_names, - verbosity=0, interactive=False): - """ - Sends a post_syncdb signal for the model specified. - - If the model is not found (perhaps it's been deleted?), - no signal is sent. - - TODO: The behavior of django.contrib.* apps seems flawed in that - they don't respect created_models. Rather, they blindly execute - over all models within the app sending the signal. This is a - patch we should push Django to make For now, this should work. - """ - - if self.debug: - print(" - Sending post_syncdb signal for %s: %s" % (app_label, model_names)) - - app = models.get_app(app_label) - if not app: - return - - created_models = [] - for model_name in model_names: - model = models.get_model(app_label, model_name) - if model: - created_models.append(model) - - if created_models: - - if hasattr(dispatcher, "send"): - # Older djangos - dispatcher.send(signal=models.signals.post_syncdb, sender=app, - app=app, created_models=created_models, - verbosity=verbosity, interactive=interactive) - else: - if self._is_multidb(): - # Django 1.2+ - models.signals.post_syncdb.send( - sender=app, - app=app, - created_models=created_models, - verbosity=verbosity, - interactive=interactive, - db=self.db_alias, - ) - else: - # Django 1.1 - 1.0 - models.signals.post_syncdb.send( - sender=app, - app=app, - created_models=created_models, - verbosity=verbosity, - interactive=interactive, - ) - - def mock_model(self, model_name, db_table, db_tablespace='', - pk_field_name='id', pk_field_type=models.AutoField, - pk_field_args=[], pk_field_kwargs={}): - """ - Generates a MockModel class that provides enough information - to be used by a foreign key/many-to-many relationship. - - Migrations should prefer to use these rather than actual models - as models could get deleted over time, but these can remain in - migration files forever. - - Depreciated. - """ - class MockOptions(object): - def __init__(self): - self.db_table = db_table - self.db_tablespace = db_tablespace or settings.DEFAULT_TABLESPACE - self.object_name = model_name - self.module_name = model_name.lower() - - if pk_field_type == models.AutoField: - pk_field_kwargs['primary_key'] = True - - self.pk = pk_field_type(*pk_field_args, **pk_field_kwargs) - self.pk.set_attributes_from_name(pk_field_name) - self.abstract = False - - def get_field_by_name(self, field_name): - # we only care about the pk field - return (self.pk, self.model, True, False) - - def get_field(self, name): - # we only care about the pk field - return self.pk - - class MockModel(object): - _meta = None - - # We need to return an actual class object here, not an instance - MockModel._meta = MockOptions() - MockModel._meta.model = MockModel - return MockModel - - def _db_positive_type_for_alter_column(self, klass, field): - """ - A helper for subclasses overriding _db_type_for_alter_column: - Remove the check constraint from the type string for PositiveInteger - and PositiveSmallInteger fields. - @param klass: The type of the child (required to allow this to be used when it is subclassed) - @param field: The field to generate type for - """ - super_result = super(klass, self)._db_type_for_alter_column(field) - if isinstance(field, (models.PositiveSmallIntegerField, models.PositiveIntegerField)): - return super_result.split(" ", 1)[0] - return super_result - - def _alter_add_positive_check(self, klass, field, name, params, sqls): - """ - A helper for subclasses overriding _alter_add_column_mods: - Add a check constraint verifying positivity to PositiveInteger and - PositiveSmallInteger fields. - """ - super(klass, self)._alter_add_column_mods(field, name, params, sqls) - if isinstance(field, (models.PositiveSmallIntegerField, models.PositiveIntegerField)): - uniq_hash = abs(hash(tuple(params.values()))) - d = dict( - constraint = "CK_%s_PSTV_%s" % (name, hex(uniq_hash)[2:]), - check = "%s >= 0" % self.quote_name(name)) - sqls.append((self.add_check_constraint_fragment % d, [])) - - -# Single-level flattening of lists -def flatten(ls): - nl = [] - for l in ls: - nl += l - return nl diff --git a/lib/python2.7/site-packages/south/db/mysql.py b/lib/python2.7/site-packages/south/db/mysql.py deleted file mode 100644 index 3e87464..0000000 --- a/lib/python2.7/site-packages/south/db/mysql.py +++ /dev/null @@ -1,290 +0,0 @@ -# MySQL-specific implementations for south -# Original author: Andrew Godwin -# Patches by: F. Gabriel Gosselin <gabrielNOSPAM@evidens.ca> - -from south.db import generic -from south.db.generic import DryRunError, INVALID -from south.logger import get_logger - - -def delete_column_constraints(func): - """ - Decorates column operation functions for MySQL. - Deletes the constraints from the database and clears local cache. - """ - def _column_rm(self, table_name, column_name, *args, **opts): - # Delete foreign key constraints - try: - self.delete_foreign_key(table_name, column_name) - except ValueError: - pass # If no foreign key on column, OK because it checks first - # Delete constraints referring to this column - try: - reverse = self._lookup_reverse_constraint(table_name, column_name) - for cname, rtable, rcolumn in reverse: - self.delete_foreign_key(rtable, rcolumn) - except DryRunError: - pass - return func(self, table_name, column_name, *args, **opts) - return _column_rm - - -def copy_column_constraints(func): - """ - Decorates column operation functions for MySQL. - Determines existing constraints and copies them to a new column - """ - def _column_cp(self, table_name, column_old, column_new, *args, **opts): - # Copy foreign key constraint - try: - constraint = self._find_foreign_constraints( - table_name, column_old)[0] - refs = self._lookup_constraint_references(table_name, constraint) - if refs is not None: - (ftable, fcolumn) = refs - if ftable and fcolumn: - fk_sql = self.foreign_key_sql( - table_name, column_new, ftable, fcolumn) - get_logger().debug("Foreign key SQL: " + fk_sql) - self.add_deferred_sql(fk_sql) - except IndexError: - pass # No constraint exists so ignore - except DryRunError: - pass - # Copy constraints referring to this column - try: - reverse = self._lookup_reverse_constraint(table_name, column_old) - for cname, rtable, rcolumn in reverse: - fk_sql = self.foreign_key_sql( - rtable, rcolumn, table_name, column_new) - self.add_deferred_sql(fk_sql) - except DryRunError: - pass - return func(self, table_name, column_old, column_new, *args, **opts) - return _column_cp - - -def invalidate_table_constraints(func): - """ - For MySQL we grab all table constraints simultaneously, so this is - effective. - It further solves the issues of invalidating referred table constraints. - """ - def _cache_clear(self, table, *args, **opts): - db_name = self._get_setting('NAME') - if db_name in self._constraint_cache: - del self._constraint_cache[db_name] - if db_name in self._reverse_cache: - del self._reverse_cache[db_name] - if db_name in self._constraint_references: - del self._constraint_references[db_name] - return func(self, table, *args, **opts) - return _cache_clear - - -class DatabaseOperations(generic.DatabaseOperations): - """ - MySQL implementation of database operations. - - MySQL has no DDL transaction support This can confuse people when they ask - how to roll back - hence the dry runs, etc., found in the migration code. - """ - - backend_name = "mysql" - alter_string_set_type = '' - alter_string_set_null = 'MODIFY %(column)s %(type)s NULL;' - alter_string_drop_null = 'MODIFY %(column)s %(type)s NOT NULL;' - drop_index_string = 'DROP INDEX %(index_name)s ON %(table_name)s' - delete_primary_key_sql = "ALTER TABLE %(table)s DROP PRIMARY KEY" - delete_foreign_key_sql = "ALTER TABLE %(table)s DROP FOREIGN KEY %(constraint)s" - delete_unique_sql = "ALTER TABLE %s DROP INDEX %s" - rename_table_sql = "RENAME TABLE %s TO %s;" - - allows_combined_alters = False - has_check_constraints = False - raises_default_errors = False - - geom_types = ['geometry', 'point', 'linestring', 'polygon'] - text_types = ['text', 'blob'] - - def __init__(self, db_alias): - self._constraint_references = {} - self._reverse_cache = {} - super(DatabaseOperations, self).__init__(db_alias) - if self._has_setting('STORAGE_ENGINE') and self._get_setting('STORAGE_ENGINE'): - self.create_table_sql = self.create_table_sql + ' ENGINE=%s' % self._get_setting('STORAGE_ENGINE') - - def _is_valid_cache(self, db_name, table_name): - cache = self._constraint_cache - # we cache the whole db so if there are any tables table_name is valid - return db_name in cache and cache[db_name].get(table_name, None) is not INVALID - - def _fill_constraint_cache(self, db_name, table_name): - # for MySQL grab all constraints for this database. It's just as cheap as a single column. - self._constraint_cache[db_name] = {} - self._constraint_cache[db_name][table_name] = {} - self._reverse_cache[db_name] = {} - self._constraint_references[db_name] = {} - - name_query = """ - SELECT kc.`constraint_name`, kc.`column_name`, kc.`table_name`, - kc.`referenced_table_name`, kc.`referenced_column_name` - FROM information_schema.key_column_usage AS kc - WHERE - kc.table_schema = %s - """ - rows = self.execute(name_query, [db_name]) - if not rows: - return - cnames = {} - for constraint, column, table, ref_table, ref_column in rows: - key = (table, constraint) - cnames.setdefault(key, set()) - cnames[key].add((column, ref_table, ref_column)) - - type_query = """ - SELECT c.constraint_name, c.table_name, c.constraint_type - FROM information_schema.table_constraints AS c - WHERE - c.table_schema = %s - """ - rows = self.execute(type_query, [db_name]) - for constraint, table, kind in rows: - key = (table, constraint) - self._constraint_cache[db_name].setdefault(table, {}) - try: - cols = cnames[key] - except KeyError: - cols = set() - for column_set in cols: - (column, ref_table, ref_column) = column_set - self._constraint_cache[db_name][table].setdefault(column, set()) - if kind == 'FOREIGN KEY': - self._constraint_cache[db_name][table][column].add((kind, - constraint)) - # Create constraint lookup, see constraint_references - self._constraint_references[db_name][(table, - constraint)] = (ref_table, ref_column) - # Create reverse table lookup, reverse_lookup - self._reverse_cache[db_name].setdefault(ref_table, {}) - self._reverse_cache[db_name][ref_table].setdefault(ref_column, - set()) - self._reverse_cache[db_name][ref_table][ref_column].add( - (constraint, table, column)) - else: - self._constraint_cache[db_name][table][column].add((kind, - constraint)) - - def connection_init(self): - """ - Run before any SQL to let database-specific config be sent as a command, - e.g. which storage engine (MySQL) or transaction serialisability level. - """ - cursor = self._get_connection().cursor() - if cursor.execute("SHOW variables WHERE Variable_Name='default_storage_engine';"): - engine_var = 'default_storage_engine' - else: - engine_var = 'storage_engine' - if self._has_setting('STORAGE_ENGINE') and self._get_setting('STORAGE_ENGINE'): - cursor.execute("SET %s=%s;" % (engine_var, self._get_setting('STORAGE_ENGINE'))) - - def start_transaction(self): - super(DatabaseOperations, self).start_transaction() - self.execute("SET FOREIGN_KEY_CHECKS=0;") - - @copy_column_constraints - @delete_column_constraints - @invalidate_table_constraints - def rename_column(self, table_name, old, new): - if old == new or self.dry_run: - return [] - - rows = [x for x in self.execute('DESCRIBE %s' % (self.quote_name(table_name),)) if x[0] == old] - - if not rows: - raise ValueError("No column '%s' in '%s'." % (old, table_name)) - - params = ( - self.quote_name(table_name), - self.quote_name(old), - self.quote_name(new), - rows[0][1], - rows[0][2] == "YES" and "NULL" or "NOT NULL", - rows[0][4] and "DEFAULT " or "", - rows[0][4] and "%s" or "", - rows[0][5] or "", - ) - - sql = 'ALTER TABLE %s CHANGE COLUMN %s %s %s %s %s %s %s;' % params - - if rows[0][4]: - self.execute(sql, (rows[0][4],)) - else: - self.execute(sql) - - @delete_column_constraints - def delete_column(self, table_name, name): - super(DatabaseOperations, self).delete_column(table_name, name) - - @invalidate_table_constraints - def rename_table(self, old_table_name, table_name): - super(DatabaseOperations, self).rename_table(old_table_name, - table_name) - - @invalidate_table_constraints - def delete_table(self, table_name): - super(DatabaseOperations, self).delete_table(table_name) - - def _lookup_constraint_references(self, table_name, cname): - """ - Provided an existing table and constraint, returns tuple of (foreign - table, column) - """ - db_name = self._get_setting('NAME') - try: - return self._constraint_references[db_name][(table_name, cname)] - except KeyError: - return None - - def _lookup_reverse_constraint(self, table_name, column_name=None): - """Look for the column referenced by a foreign constraint""" - db_name = self._get_setting('NAME') - if self.dry_run: - raise DryRunError("Cannot get constraints for columns.") - - if not self._is_valid_cache(db_name, table_name): - # Piggy-back on lookup_constraint, ensures cache exists - self.lookup_constraint(db_name, table_name) - - try: - table = self._reverse_cache[db_name][table_name] - if column_name == None: - return [(y, tuple(y)) for x, y in table.items()] - else: - return tuple(table[column_name]) - except KeyError: - return [] - - def _field_sanity(self, field): - """ - This particular override stops us sending DEFAULTs for BLOB/TEXT columns. - """ - # MySQL does not support defaults for geometry columns also - type = self._db_type_for_alter_column(field).lower() - is_geom = True in [type.find(t) > -1 for t in self.geom_types] - is_text = True in [type.find(t) > -1 for t in self.text_types] - - if is_geom or is_text: - field._suppress_default = True - return field - - def _alter_set_defaults(self, field, name, params, sqls): - """ - MySQL does not support defaults on text or blob columns. - """ - type = params['type'] - # MySQL does not support defaults for geometry columns also - is_geom = True in [type.find(t) > -1 for t in self.geom_types] - is_text = True in [type.find(t) > -1 for t in self.text_types] - if not is_geom and not is_text: - super(DatabaseOperations, self)._alter_set_defaults(field, name, params, sqls) diff --git a/lib/python2.7/site-packages/south/db/oracle.py b/lib/python2.7/site-packages/south/db/oracle.py deleted file mode 100644 index 79496d0..0000000 --- a/lib/python2.7/site-packages/south/db/oracle.py +++ /dev/null @@ -1,345 +0,0 @@ -from __future__ import print_function
-
-import os.path
-import sys
-import re
-import warnings
-import cx_Oracle
-
-
-from django.db import connection, models
-from django.db.backends.util import truncate_name
-from django.core.management.color import no_style
-from django.db.models.fields import NOT_PROVIDED
-from django.db.utils import DatabaseError
-
-# In revision r16016 function get_sequence_name has been transformed into
-# method of DatabaseOperations class. To make code backward-compatible we
-# need to handle both situations.
-try:
- from django.db.backends.oracle.base import get_sequence_name\
- as original_get_sequence_name
-except ImportError:
- original_get_sequence_name = None
-
-from south.db import generic
-
-class DatabaseOperations(generic.DatabaseOperations):
- """
- Oracle implementation of database operations.
- """
- backend_name = 'oracle'
-
- alter_string_set_type = 'ALTER TABLE %(table_name)s MODIFY %(column)s %(type)s %(nullity)s;'
- alter_string_set_default = 'ALTER TABLE %(table_name)s MODIFY %(column)s DEFAULT %(default)s;'
- alter_string_update_nulls_to_default = \
- 'UPDATE %(table_name)s SET %(column)s = %(default)s WHERE %(column)s IS NULL;'
- add_column_string = 'ALTER TABLE %s ADD %s;'
- delete_column_string = 'ALTER TABLE %s DROP COLUMN %s;'
- add_constraint_string = 'ALTER TABLE %(table_name)s ADD CONSTRAINT %(constraint)s %(clause)s'
-
- allows_combined_alters = False
- has_booleans = False
-
- constraints_dict = {
- 'P': 'PRIMARY KEY',
- 'U': 'UNIQUE',
- 'C': 'CHECK',
- 'R': 'FOREIGN KEY'
- }
-
- def get_sequence_name(self, table_name):
- if original_get_sequence_name is None:
- return self._get_connection().ops._get_sequence_name(table_name)
- else:
- return original_get_sequence_name(table_name)
-
- #TODO: This will cause very obscure bugs if anyone uses a column name or string value
- # that looks like a column definition (with 'CHECK', 'DEFAULT' and/or 'NULL' in it)
- # e.g. "CHECK MATE" varchar(10) DEFAULT 'NULL'
- def adj_column_sql(self, col):
- # Syntax fixes -- Oracle is picky about clause order
- col = re.sub('(?P<constr>CHECK \(.*\))(?P<any>.*)(?P<default>DEFAULT \d+)',
- lambda mo: '%s %s%s'%(mo.group('default'), mo.group('constr'), mo.group('any')), col) #syntax fix for boolean/integer field only
- col = re.sub('(?P<not_null>(NOT )?NULL) (?P<misc>(.* )?)(?P<default>DEFAULT.+)',
- lambda mo: '%s %s %s'%(mo.group('default'),mo.group('not_null'),mo.group('misc') or ''), col) #fix order of NULL/NOT NULL and DEFAULT
- return col
-
- def check_meta(self, table_name):
- return table_name in [ m._meta.db_table for m in models.get_models() ] #caching provided by Django
-
- def normalize_name(self, name):
- """
- Get the properly shortened and uppercased identifier as returned by quote_name(), but without the actual quotes.
- """
- nn = self.quote_name(name)
- if nn[0] == '"' and nn[-1] == '"':
- nn = nn[1:-1]
- return nn
-
- @generic.invalidate_table_constraints
- def create_table(self, table_name, fields):
- qn = self.quote_name(table_name)
- columns = []
- autoinc_sql = ''
-
-
- for field_name, field in fields:
-
- field = self._field_sanity(field)
-
- # avoid default values in CREATE TABLE statements (#925)
- field._suppress_default = True
-
-
- col = self.column_sql(table_name, field_name, field)
- if not col:
- continue
- col = self.adj_column_sql(col)
-
- columns.append(col)
- if isinstance(field, models.AutoField):
- autoinc_sql = connection.ops.autoinc_sql(table_name, field_name)
-
- sql = 'CREATE TABLE %s (%s);' % (qn, ', '.join([col for col in columns]))
- self.execute(sql)
- if autoinc_sql:
- self.execute(autoinc_sql[0])
- self.execute(autoinc_sql[1])
-
- @generic.invalidate_table_constraints
- def delete_table(self, table_name, cascade=True):
- qn = self.quote_name(table_name)
-
- # Note: PURGE is not valid syntax for Oracle 9i (it was added in 10)
- if cascade:
- self.execute('DROP TABLE %s CASCADE CONSTRAINTS;' % qn)
- else:
- self.execute('DROP TABLE %s;' % qn)
-
- # If the table has an AutoField a sequence was created.
- sequence_sql = """
-DECLARE
- i INTEGER;
-BEGIN
- SELECT COUNT(*) INTO i FROM USER_CATALOG
- WHERE TABLE_NAME = '%(sq_name)s' AND TABLE_TYPE = 'SEQUENCE';
- IF i = 1 THEN
- EXECUTE IMMEDIATE 'DROP SEQUENCE "%(sq_name)s"';
- END IF;
-END;
-/""" % {'sq_name': self.get_sequence_name(table_name)}
- self.execute(sequence_sql)
-
- @generic.invalidate_table_constraints
- def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False):
-
- if self.dry_run:
- if self.debug:
- print(' - no dry run output for alter_column() due to dynamic DDL, sorry')
- return
-
- qn = self.quote_name(table_name)
-
- # hook for the field to do any resolution prior to it's attributes being queried
- if hasattr(field, 'south_init'):
- field.south_init()
- field = self._field_sanity(field)
-
- # Add _id or whatever if we need to
- field.set_attributes_from_name(name)
- if not explicit_name:
- name = field.column
- qn_col = self.quote_name(name)
-
- # First, change the type
- # This will actually also add any CHECK constraints needed,
- # since e.g. 'type' for a BooleanField is 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))'
- params = {
- 'table_name':qn,
- 'column': qn_col,
- 'type': self._db_type_for_alter_column(field),
- 'nullity': 'NOT NULL',
- 'default': 'NULL'
- }
- if field.null:
- params['nullity'] = 'NULL'
-
- sql_templates = [
- (self.alter_string_set_type, params, []),
- (self.alter_string_set_default, params, []),
- ]
- if not field.null and field.has_default():
- # Use default for rows that had nulls. To support the case where
- # the new default does not fit the old type, we need to first change
- # the column type to the new type, but null=True; then set the default;
- # then complete the type change.
- def change_params(**kw):
- "A little helper for non-destructively changing the params"
- p = params.copy()
- p.update(kw)
- return p
- sql_templates[:0] = [
- (self.alter_string_set_type, change_params(nullity='NULL'),[]),
- (self.alter_string_update_nulls_to_default, change_params(default="%s"), [field.get_default()]),
- ]
-
- if not ignore_constraints:
- # drop CHECK constraints. Make sure this is executed before the ALTER TABLE statements
- # generated above, since those statements recreate the constraints we delete here.
- check_constraints = self._constraints_affecting_columns(table_name, [name], "CHECK")
- for constraint in check_constraints:
- self.execute(self.delete_check_sql % {
- 'table': self.quote_name(table_name),
- 'constraint': self.quote_name(constraint),
- })
- # Drop foreign constraints
- try:
- self.delete_foreign_key(qn, qn_col)
- except ValueError:
- # There weren't any
- pass
-
- for sql_template, params, args in sql_templates:
- try:
- self.execute(sql_template % params, args, print_all_errors=False)
- except DatabaseError as exc:
- description = str(exc)
- # Oracle complains if a column is already NULL/NOT NULL
- if 'ORA-01442' in description or 'ORA-01451' in description:
- # so we just drop NULL/NOT NULL part from target sql and retry
- params['nullity'] = ''
- sql = sql_template % params
- self.execute(sql)
- # Oracle also has issues if we try to change a regular column
- # to a LOB or vice versa (also REF, object, VARRAY or nested
- # table, but these don't come up much in Django apps)
- elif 'ORA-22858' in description or 'ORA-22859' in description:
- self._alter_column_lob_workaround(table_name, name, field)
- else:
- self._print_sql_error(exc, sql_template % params)
- raise
-
- if not ignore_constraints:
- # Add back FK constraints if needed
- if field.rel: #and self.supports_foreign_keys:
- self.add_deferred_sql(
- self.foreign_key_sql(
- qn[1:-1], # foreign_key_sql uses this as part of constraint name
- qn_col[1:-1], # foreign_key_sql uses this as part of constraint name
- field.rel.to._meta.db_table,
- field.rel.to._meta.get_field(field.rel.field_name).column
- )
- )
-
-
- def _alter_column_lob_workaround(self, table_name, name, field):
- """
- Oracle refuses to change a column type from/to LOB to/from a regular
- column. In Django, this shows up when the field is changed from/to
- a TextField.
- What we need to do instead is:
- - Rename the original column
- - Add the desired field as new
- - Update the table to transfer values from old to new
- - Drop old column
- """
- renamed = self._generate_temp_name(name)
- self.rename_column(table_name, name, renamed)
- self.add_column(table_name, name, field, keep_default=False)
- self.execute("UPDATE %s set %s=%s" % (
- self.quote_name(table_name),
- self.quote_name(name),
- self.quote_name(renamed),
- ))
- self.delete_column(table_name, renamed)
-
- def _generate_temp_name(self, for_name):
- suffix = hex(hash(for_name)).upper()[1:]
- return self.normalize_name(for_name + "_" + suffix)
-
- @generic.copy_column_constraints #TODO: Appears to be nulled by the delete decorator below...
- @generic.delete_column_constraints
- def rename_column(self, table_name, old, new):
- if old == new:
- # Short-circuit out
- return []
- self.execute('ALTER TABLE %s RENAME COLUMN %s TO %s;' % (
- self.quote_name(table_name),
- self.quote_name(old),
- self.quote_name(new),
- ))
-
- @generic.invalidate_table_constraints
- def add_column(self, table_name, name, field, keep_default=False):
- field = self._field_sanity(field)
- sql = self.column_sql(table_name, name, field)
- sql = self.adj_column_sql(sql)
-
- if sql:
- params = (
- self.quote_name(table_name),
- sql
- )
- sql = self.add_column_string % params
- self.execute(sql)
-
- # Now, drop the default if we need to
- if field.default is not None:
- field.default = NOT_PROVIDED
- self.alter_column(table_name, name, field, explicit_name=False, ignore_constraints=True)
-
- def delete_column(self, table_name, name):
- return super(DatabaseOperations, self).delete_column(self.quote_name(table_name), name)
-
- def lookup_constraint(self, db_name, table_name, column_name=None):
- if column_name:
- # Column names in the constraint cache come from the database,
- # make sure we use the properly shortened/uppercased version
- # for lookup.
- column_name = self.normalize_name(column_name)
- return super(DatabaseOperations, self).lookup_constraint(db_name, table_name, column_name)
-
- def _constraints_affecting_columns(self, table_name, columns, type="UNIQUE"):
- if columns:
- columns = [self.normalize_name(c) for c in columns]
- return super(DatabaseOperations, self)._constraints_affecting_columns(table_name, columns, type)
-
- def _field_sanity(self, field):
- """
- This particular override stops us sending DEFAULTs for BooleanField.
- """
- if isinstance(field, models.BooleanField) and field.has_default():
- field.default = int(field.to_python(field.get_default()))
- # On Oracle, empty strings are null
- if isinstance(field, (models.CharField, models.TextField)):
- field.null = field.empty_strings_allowed
- return field
-
-
- def _default_value_workaround(self, value):
- from datetime import date,time,datetime
- if isinstance(value, (date,time,datetime)):
- return "'%s'" % value
- else:
- return super(DatabaseOperations, self)._default_value_workaround(value)
-
- def _fill_constraint_cache(self, db_name, table_name):
- self._constraint_cache.setdefault(db_name, {})
- self._constraint_cache[db_name][table_name] = {}
-
- rows = self.execute("""
- SELECT user_cons_columns.constraint_name,
- user_cons_columns.column_name,
- user_constraints.constraint_type
- FROM user_constraints
- JOIN user_cons_columns ON
- user_constraints.table_name = user_cons_columns.table_name AND
- user_constraints.constraint_name = user_cons_columns.constraint_name
- WHERE user_constraints.table_name = '%s'
- """ % self.normalize_name(table_name))
-
- for constraint, column, kind in rows:
- self._constraint_cache[db_name][table_name].setdefault(column, set())
- self._constraint_cache[db_name][table_name][column].add((self.constraints_dict[kind], constraint))
- return
diff --git a/lib/python2.7/site-packages/south/db/postgresql_psycopg2.py b/lib/python2.7/site-packages/south/db/postgresql_psycopg2.py deleted file mode 100644 index d6c63c4..0000000 --- a/lib/python2.7/site-packages/south/db/postgresql_psycopg2.py +++ /dev/null @@ -1,96 +0,0 @@ -from __future__ import print_function - -import uuid -from django.db.backends.util import truncate_name -from south.db import generic - - -class DatabaseOperations(generic.DatabaseOperations): - - """ - PsycoPG2 implementation of database operations. - """ - - backend_name = "postgres" - - def create_index_name(self, table_name, column_names, suffix=""): - """ - Generate a unique name for the index - - Django's logic for naming field indexes is different in the - postgresql_psycopg2 backend, so we follow that for single-column - indexes. - """ - - if len(column_names) == 1: - return truncate_name( - '%s_%s%s' % (table_name, column_names[0], suffix), - self._get_connection().ops.max_name_length() - ) - return super(DatabaseOperations, self).create_index_name(table_name, column_names, suffix) - - @generic.copy_column_constraints - @generic.delete_column_constraints - def rename_column(self, table_name, old, new): - if old == new: - # Short-circuit out - return [] - self.execute('ALTER TABLE %s RENAME COLUMN %s TO %s;' % ( - self.quote_name(table_name), - self.quote_name(old), - self.quote_name(new), - )) - - @generic.invalidate_table_constraints - def rename_table(self, old_table_name, table_name): - "will rename the table and an associated ID sequence and primary key index" - # First, rename the table - generic.DatabaseOperations.rename_table(self, old_table_name, table_name) - # Then, try renaming the ID sequence - # (if you're using other AutoFields... your problem, unfortunately) - - if self.execute( - """ - SELECT 1 - FROM information_schema.sequences - WHERE sequence_name = %s - """, - [old_table_name + '_id_seq'] - ): - generic.DatabaseOperations.rename_table(self, old_table_name + "_id_seq", table_name + "_id_seq") - - # Rename primary key index, will not rename other indices on - # the table that are used by django (e.g. foreign keys). Until - # figure out how, you need to do this yourself. - - pkey_index_names = self.execute( - """ - SELECT pg_index.indexrelid::regclass - FROM pg_index, pg_attribute - WHERE - indrelid = %s::regclass AND - pg_attribute.attrelid = indrelid AND - pg_attribute.attnum = any(pg_index.indkey) - AND indisprimary - """, - [table_name] - ) - if old_table_name + "_pkey" in pkey_index_names: - generic.DatabaseOperations.rename_table(self, old_table_name + "_pkey", table_name + "_pkey") - - def rename_index(self, old_index_name, index_name): - "Rename an index individually" - generic.DatabaseOperations.rename_table(self, old_index_name, index_name) - - def _default_value_workaround(self, value): - "Support for UUIDs on psql" - if isinstance(value, uuid.UUID): - return str(value) - else: - return super(DatabaseOperations, self)._default_value_workaround(value) - - def _db_type_for_alter_column(self, field): - return self._db_positive_type_for_alter_column(DatabaseOperations, field) - - def _alter_add_column_mods(self, field, name, params, sqls): - return self._alter_add_positive_check(DatabaseOperations, field, name, params, sqls) diff --git a/lib/python2.7/site-packages/south/db/sql_server/__init__.py b/lib/python2.7/site-packages/south/db/sql_server/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/db/sql_server/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/db/sql_server/pyodbc.py b/lib/python2.7/site-packages/south/db/sql_server/pyodbc.py deleted file mode 100644 index b725ec0..0000000 --- a/lib/python2.7/site-packages/south/db/sql_server/pyodbc.py +++ /dev/null @@ -1,444 +0,0 @@ -from datetime import date, datetime, time -from warnings import warn -from django.db import models -from django.db.models import fields -from south.db import generic -from south.db.generic import delete_column_constraints, invalidate_table_constraints, copy_column_constraints -from south.exceptions import ConstraintDropped -from south.utils.py3 import string_types -try: - from django.utils.encoding import smart_text # Django >= 1.5 -except ImportError: - from django.utils.encoding import smart_unicode as smart_text # Django < 1.5 -from django.core.management.color import no_style - -class DatabaseOperations(generic.DatabaseOperations): - """ - django-pyodbc (sql_server.pyodbc) implementation of database operations. - """ - - backend_name = "pyodbc" - - add_column_string = 'ALTER TABLE %s ADD %s;' - alter_string_set_type = 'ALTER COLUMN %(column)s %(type)s' - alter_string_set_null = 'ALTER COLUMN %(column)s %(type)s NULL' - alter_string_drop_null = 'ALTER COLUMN %(column)s %(type)s NOT NULL' - - allows_combined_alters = False - - drop_index_string = 'DROP INDEX %(index_name)s ON %(table_name)s' - drop_constraint_string = 'ALTER TABLE %(table_name)s DROP CONSTRAINT %(constraint_name)s' - delete_column_string = 'ALTER TABLE %s DROP COLUMN %s' - - #create_check_constraint_sql = "ALTER TABLE %(table)s " + \ - # generic.DatabaseOperations.add_check_constraint_fragment - create_foreign_key_sql = "ALTER TABLE %(table)s ADD CONSTRAINT %(constraint)s " + \ - "FOREIGN KEY (%(column)s) REFERENCES %(target)s" - create_unique_sql = "ALTER TABLE %(table)s ADD CONSTRAINT %(constraint)s UNIQUE (%(columns)s)" - - - default_schema_name = "dbo" - - has_booleans = False - - - @delete_column_constraints - def delete_column(self, table_name, name): - q_table_name, q_name = (self.quote_name(table_name), self.quote_name(name)) - - # Zap the constraints - for const in self._find_constraints_for_column(table_name,name): - params = {'table_name':q_table_name, 'constraint_name': const} - sql = self.drop_constraint_string % params - self.execute(sql, []) - - # Zap the indexes - for ind in self._find_indexes_for_column(table_name,name): - params = {'table_name':q_table_name, 'index_name': ind} - sql = self.drop_index_string % params - self.execute(sql, []) - - # Zap default if exists - drop_default = self.drop_column_default_sql(table_name, name) - if drop_default: - sql = "ALTER TABLE [%s] %s" % (table_name, drop_default) - self.execute(sql, []) - - # Finally zap the column itself - self.execute(self.delete_column_string % (q_table_name, q_name), []) - - def _find_indexes_for_column(self, table_name, name): - "Find the indexes that apply to a column, needed when deleting" - - sql = """ - SELECT si.name, si.id, sik.colid, sc.name - FROM dbo.sysindexes si WITH (NOLOCK) - INNER JOIN dbo.sysindexkeys sik WITH (NOLOCK) - ON sik.id = si.id - AND sik.indid = si.indid - INNER JOIN dbo.syscolumns sc WITH (NOLOCK) - ON si.id = sc.id - AND sik.colid = sc.colid - WHERE si.indid !=0 - AND si.id = OBJECT_ID('%s') - AND sc.name = '%s' - """ - idx = self.execute(sql % (table_name, name), []) - return [i[0] for i in idx] - - - def _find_constraints_for_column(self, table_name, name, just_names=True): - """ - Find the constraints that apply to a column, needed when deleting. Defaults not included. - This is more general than the parent _constraints_affecting_columns, as on MSSQL this - includes PK and FK constraints. - """ - - sql = """ - SELECT CC.[CONSTRAINT_NAME] - ,TC.[CONSTRAINT_TYPE] - ,CHK.[CHECK_CLAUSE] - ,RFD.TABLE_SCHEMA - ,RFD.TABLE_NAME - ,RFD.COLUMN_NAME - -- used for normalized names - ,CC.TABLE_NAME - ,CC.COLUMN_NAME - FROM [INFORMATION_SCHEMA].[TABLE_CONSTRAINTS] TC - JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE CC - ON TC.CONSTRAINT_CATALOG = CC.CONSTRAINT_CATALOG - AND TC.CONSTRAINT_SCHEMA = CC.CONSTRAINT_SCHEMA - AND TC.CONSTRAINT_NAME = CC.CONSTRAINT_NAME - LEFT JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS CHK - ON CHK.CONSTRAINT_CATALOG = CC.CONSTRAINT_CATALOG - AND CHK.CONSTRAINT_SCHEMA = CC.CONSTRAINT_SCHEMA - AND CHK.CONSTRAINT_NAME = CC.CONSTRAINT_NAME - AND 'CHECK' = TC.CONSTRAINT_TYPE - LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS REF - ON REF.CONSTRAINT_CATALOG = CC.CONSTRAINT_CATALOG - AND REF.CONSTRAINT_SCHEMA = CC.CONSTRAINT_SCHEMA - AND REF.CONSTRAINT_NAME = CC.CONSTRAINT_NAME - AND 'FOREIGN KEY' = TC.CONSTRAINT_TYPE - LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE RFD - ON RFD.CONSTRAINT_CATALOG = REF.UNIQUE_CONSTRAINT_CATALOG - AND RFD.CONSTRAINT_SCHEMA = REF.UNIQUE_CONSTRAINT_SCHEMA - AND RFD.CONSTRAINT_NAME = REF.UNIQUE_CONSTRAINT_NAME - WHERE CC.CONSTRAINT_CATALOG = CC.TABLE_CATALOG - AND CC.CONSTRAINT_SCHEMA = CC.TABLE_SCHEMA - AND CC.TABLE_CATALOG = %s - AND CC.TABLE_SCHEMA = %s - AND CC.TABLE_NAME = %s - AND CC.COLUMN_NAME = %s - """ - db_name = self._get_setting('name') - schema_name = self._get_schema_name() - table = self.execute(sql, [db_name, schema_name, table_name, name]) - - if just_names: - return [r[0] for r in table] - - all = {} - for r in table: - cons_name, type = r[:2] - if type=='PRIMARY KEY' or type=='UNIQUE': - cons = all.setdefault(cons_name, (type,[])) - sql = ''' - SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE RFD - WHERE RFD.CONSTRAINT_CATALOG = %s - AND RFD.CONSTRAINT_SCHEMA = %s - AND RFD.TABLE_NAME = %s - AND RFD.CONSTRAINT_NAME = %s - ''' - columns = self.execute(sql, [db_name, schema_name, table_name, cons_name]) - cons[1].extend(col for col, in columns) - elif type=='CHECK': - cons = (type, r[2]) - elif type=='FOREIGN KEY': - if cons_name in all: - raise NotImplementedError("Multiple-column foreign keys are not supported") - else: - cons = (type, r[3:6]) - else: - raise NotImplementedError("Don't know how to handle constraints of type "+ type) - all[cons_name] = cons - return all - - @invalidate_table_constraints - def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False): - """ - Alters the given column name so it will match the given field. - Note that conversion between the two by the database must be possible. - Will not automatically add _id by default; to have this behavour, pass - explicit_name=False. - - @param table_name: The name of the table to add the column to - @param name: The name of the column to alter - @param field: The new field definition to use - """ - self._fix_field_definition(field) - - if not ignore_constraints: - qn = self.quote_name - sch = qn(self._get_schema_name()) - tab = qn(table_name) - table = ".".join([sch, tab]) - try: - self.delete_foreign_key(table_name, name) - except ValueError: - # no FK constraint on this field. That's OK. - pass - constraints = self._find_constraints_for_column(table_name, name, False) - for constraint in constraints.keys(): - params = dict(table_name = table, - constraint_name = qn(constraint)) - sql = self.drop_constraint_string % params - self.execute(sql, []) - - ret_val = super(DatabaseOperations, self).alter_column(table_name, name, field, explicit_name, ignore_constraints=True) - - if not ignore_constraints: - for cname, (ctype,args) in constraints.items(): - params = dict(table = table, - constraint = qn(cname)) - if ctype=='UNIQUE': - params['columns'] = ", ".join(map(qn,args)) - sql = self.create_unique_sql % params - elif ctype=='PRIMARY KEY': - params['columns'] = ", ".join(map(qn,args)) - sql = self.create_primary_key_string % params - elif ctype=='FOREIGN KEY': - continue - # Foreign keys taken care of below - #target = "%s.%s(%s)" % tuple(map(qn,args)) - #params.update(column = qn(name), target = target) - #sql = self.create_foreign_key_sql % params - elif ctype=='CHECK': - warn(ConstraintDropped("CHECK "+ args, table_name, name)) - continue - #TODO: Some check constraints should be restored; but not before the generic - # backend restores them. - #params['check'] = args - #sql = self.create_check_constraint_sql % params - else: - raise NotImplementedError("Don't know how to handle constraints of type "+ type) - self.execute(sql, []) - # Create foreign key if necessary - if field.rel and self.supports_foreign_keys: - self.execute( - self.foreign_key_sql( - table_name, - field.column, - field.rel.to._meta.db_table, - field.rel.to._meta.get_field(field.rel.field_name).column - ) - ) - model = self.mock_model("FakeModelForIndexCreation", table_name) - for stmt in self._get_connection().creation.sql_indexes_for_field(model, field, no_style()): - self.execute(stmt) - - - return ret_val - - def _alter_set_defaults(self, field, name, params, sqls): - "Subcommand of alter_column that sets default values (overrideable)" - # Historically, we used to set defaults here. - # But since South 0.8, we don't ever set defaults on alter-column -- we only - # use database-level defaults as scaffolding when adding columns. - # However, we still sometimes need to remove defaults in alter-column. - table_name = self.quote_name(params['table_name']) - drop_default = self.drop_column_default_sql(table_name, name) - if drop_default: - sqls.append((drop_default, [])) - - def _value_to_unquoted_literal(self, field, value): - # Start with the field's own translation - conn = self._get_connection() - value = field.get_db_prep_save(value, connection=conn) - # This is still a Python object -- nobody expects to need a literal. - if isinstance(value, string_types): - return smart_text(value) - elif isinstance(value, (date,time,datetime)): - return value.isoformat() - else: - #TODO: Anybody else needs special translations? - return str(value) - def _default_value_workaround(self, value): - if isinstance(value, (date,time,datetime)): - return value.isoformat() - else: - return super(DatabaseOperations, self)._default_value_workaround(value) - - def _quote_string(self, s): - return "'" + s.replace("'","''") + "'" - - - def drop_column_default_sql(self, table_name, name, q_name=None): - "MSSQL specific drop default, which is a pain" - - sql = """ - SELECT object_name(cdefault) - FROM syscolumns - WHERE id = object_id('%s') - AND name = '%s' - """ - cons = self.execute(sql % (table_name, name), []) - if cons and cons[0] and cons[0][0]: - return "DROP CONSTRAINT %s" % cons[0][0] - return None - - def _fix_field_definition(self, field): - if isinstance(field, (fields.BooleanField, fields.NullBooleanField)): - if field.default == True: - field.default = 1 - if field.default == False: - field.default = 0 - - # This is copied from South's generic add_column, with two modifications: - # 1) The sql-server-specific call to _fix_field_definition - # 2) Removing a default, when needed, by calling drop_default and not the more general alter_column - @invalidate_table_constraints - def add_column(self, table_name, name, field, keep_default=False): - """ - Adds the column 'name' to the table 'table_name'. - Uses the 'field' paramater, a django.db.models.fields.Field instance, - to generate the necessary sql - - @param table_name: The name of the table to add the column to - @param name: The name of the column to add - @param field: The field to use - """ - self._fix_field_definition(field) - sql = self.column_sql(table_name, name, field) - if sql: - params = ( - self.quote_name(table_name), - sql, - ) - sql = self.add_column_string % params - self.execute(sql) - - # Now, drop the default if we need to - if not keep_default and field.default is not None: - field.default = fields.NOT_PROVIDED - #self.alter_column(table_name, name, field, explicit_name=False, ignore_constraints=True) - self.drop_default(table_name, name, field) - - @invalidate_table_constraints - def drop_default(self, table_name, name, field): - fragment = self.drop_column_default_sql(table_name, name) - if fragment: - table_name = self.quote_name(table_name) - sql = " ".join(["ALTER TABLE", table_name, fragment]) - self.execute(sql) - - - @invalidate_table_constraints - def create_table(self, table_name, field_defs): - # Tweak stuff as needed - for _, f in field_defs: - self._fix_field_definition(f) - - # Run - super(DatabaseOperations, self).create_table(table_name, field_defs) - - def _find_referencing_fks(self, table_name): - "MSSQL does not support cascading FKs when dropping tables, we need to implement." - - # FK -- Foreign Keys - # UCTU -- Unique Constraints Table Usage - # FKTU -- Foreign Key Table Usage - # (last two are both really CONSTRAINT_TABLE_USAGE, different join conditions) - sql = """ - SELECT FKTU.TABLE_SCHEMA as REFING_TABLE_SCHEMA, - FKTU.TABLE_NAME as REFING_TABLE_NAME, - FK.[CONSTRAINT_NAME] as FK_NAME - FROM [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS] FK - JOIN [INFORMATION_SCHEMA].[CONSTRAINT_TABLE_USAGE] UCTU - ON FK.UNIQUE_CONSTRAINT_CATALOG = UCTU.CONSTRAINT_CATALOG and - FK.UNIQUE_CONSTRAINT_NAME = UCTU.CONSTRAINT_NAME and - FK.UNIQUE_CONSTRAINT_SCHEMA = UCTU.CONSTRAINT_SCHEMA - JOIN [INFORMATION_SCHEMA].[CONSTRAINT_TABLE_USAGE] FKTU - ON FK.CONSTRAINT_CATALOG = FKTU.CONSTRAINT_CATALOG and - FK.CONSTRAINT_NAME = FKTU.CONSTRAINT_NAME and - FK.CONSTRAINT_SCHEMA = FKTU.CONSTRAINT_SCHEMA - WHERE FK.CONSTRAINT_CATALOG = %s - AND UCTU.TABLE_SCHEMA = %s -- REFD_TABLE_SCHEMA - AND UCTU.TABLE_NAME = %s -- REFD_TABLE_NAME - """ - db_name = self._get_setting('name') - schema_name = self._get_schema_name() - return self.execute(sql, [db_name, schema_name, table_name]) - - @invalidate_table_constraints - def delete_table(self, table_name, cascade=True): - """ - Deletes the table 'table_name'. - """ - if cascade: - refing = self._find_referencing_fks(table_name) - for schmea, table, constraint in refing: - table = ".".join(map (self.quote_name, [schmea, table])) - params = dict(table_name = table, - constraint_name = self.quote_name(constraint)) - sql = self.drop_constraint_string % params - self.execute(sql, []) - cascade = False - super(DatabaseOperations, self).delete_table(table_name, cascade) - - @copy_column_constraints - @delete_column_constraints - def rename_column(self, table_name, old, new): - """ - Renames the column of 'table_name' from 'old' to 'new'. - WARNING - This isn't transactional on MSSQL! - """ - if old == new: - # No Operation - return - # Examples on the MS site show the table name not being quoted... - params = (table_name, self.quote_name(old), self.quote_name(new)) - self.execute("EXEC sp_rename '%s.%s', %s, 'COLUMN'" % params) - - @invalidate_table_constraints - def rename_table(self, old_table_name, table_name): - """ - Renames the table 'old_table_name' to 'table_name'. - WARNING - This isn't transactional on MSSQL! - """ - if old_table_name == table_name: - # No Operation - return - params = (self.quote_name(old_table_name), self.quote_name(table_name)) - self.execute('EXEC sp_rename %s, %s' % params) - - def _db_type_for_alter_column(self, field): - return self._db_positive_type_for_alter_column(DatabaseOperations, field) - - def _alter_add_column_mods(self, field, name, params, sqls): - return self._alter_add_positive_check(DatabaseOperations, field, name, params, sqls) - - @invalidate_table_constraints - def delete_foreign_key(self, table_name, column): - super(DatabaseOperations, self).delete_foreign_key(table_name, column) - # A FK also implies a non-unique index - find_index_sql = """ - SELECT i.name -- s.name, t.name, c.name - FROM sys.tables t - INNER JOIN sys.schemas s ON t.schema_id = s.schema_id - INNER JOIN sys.indexes i ON i.object_id = t.object_id - INNER JOIN sys.index_columns ic ON ic.object_id = t.object_id - AND ic.index_id = i.index_id - INNER JOIN sys.columns c ON c.object_id = t.object_id - AND ic.column_id = c.column_id - WHERE i.is_unique=0 AND i.is_primary_key=0 AND i.is_unique_constraint=0 - AND s.name = %s - AND t.name = %s - AND c.name = %s - """ - schema = self._get_schema_name() - indexes = self.execute(find_index_sql, [schema, table_name, column]) - qn = self.quote_name - for index in (i[0] for i in indexes if i[0]): # "if i[0]" added because an empty name may return - self.execute("DROP INDEX %s on %s.%s" % (qn(index), qn(schema), qn(table_name) )) - diff --git a/lib/python2.7/site-packages/south/db/sqlite3.py b/lib/python2.7/site-packages/south/db/sqlite3.py deleted file mode 100644 index c4014d3..0000000 --- a/lib/python2.7/site-packages/south/db/sqlite3.py +++ /dev/null @@ -1,272 +0,0 @@ -from south.db import generic
-
-
-class DatabaseOperations(generic.DatabaseOperations):
-
- """
- SQLite3 implementation of database operations.
- """
-
- backend_name = "sqlite3"
-
- # SQLite ignores several constraints. I wish I could.
- supports_foreign_keys = False
- has_check_constraints = False
- has_booleans = False
-
- def add_column(self, table_name, name, field, *args, **kwds):
- """
- Adds a column.
- """
- # If it's not nullable, and has no default, raise an error (SQLite is picky)
- if (not field.null and
- (not field.has_default() or field.get_default() is None) and
- not field.empty_strings_allowed):
- raise ValueError("You cannot add a null=False column without a default value.")
- # Initialise the field.
- field.set_attributes_from_name(name)
- # We add columns by remaking the table; even though SQLite supports
- # adding columns, it doesn't support adding PRIMARY KEY or UNIQUE cols.
- # We define fields with no default; a default will be used, though, to fill up the remade table
- field_default = None
- if not getattr(field, '_suppress_default', False):
- default = field.get_default()
- if default is not None:
- field_default = "'%s'" % field.get_db_prep_save(default, connection=self._get_connection())
- field._suppress_default = True
- self._remake_table(table_name, added={
- field.column: (self._column_sql_for_create(table_name, name, field, False), field_default)
- })
-
- def _get_full_table_description(self, connection, cursor, table_name):
- cursor.execute('PRAGMA table_info(%s)' % connection.ops.quote_name(table_name))
- # cid, name, type, notnull, dflt_value, pk
- return [{'name': field[1],
- 'type': field[2],
- 'null_ok': not field[3],
- 'dflt_value': field[4],
- 'pk': field[5] # undocumented
- } for field in cursor.fetchall()]
-
- @generic.invalidate_table_constraints
- def _remake_table(self, table_name, added={}, renames={}, deleted=[], altered={}, primary_key_override=None, uniques_deleted=[]):
- """
- Given a table and three sets of changes (renames, deletes, alters),
- recreates it with the modified schema.
- """
- # Dry runs get skipped completely
- if self.dry_run:
- return
- # Temporary table's name
- temp_name = "_south_new_" + table_name
- # Work out the (possibly new) definitions of each column
- definitions = {}
- cursor = self._get_connection().cursor()
- # Get the index descriptions
- indexes = self._get_connection().introspection.get_indexes(cursor, table_name)
- standalone_indexes = self._get_standalone_indexes(table_name)
- # Work out new column defs.
- for column_info in self._get_full_table_description(self._get_connection(), cursor, table_name):
- name = column_info['name']
- if name in deleted:
- continue
- # Get the type, ignoring PRIMARY KEY (we need to be consistent)
- type = column_info['type'].replace("PRIMARY KEY", "")
- # Add on primary key, not null or unique if needed.
- if (primary_key_override and primary_key_override == name) or \
- (not primary_key_override and name in indexes and
- indexes[name]['primary_key']):
- type += " PRIMARY KEY"
- elif not column_info['null_ok']:
- type += " NOT NULL"
- if (name in indexes and indexes[name]['unique'] and
- name not in uniques_deleted):
- type += " UNIQUE"
- if column_info['dflt_value'] is not None:
- type += " DEFAULT " + column_info['dflt_value']
- # Deal with a rename
- if name in renames:
- name = renames[name]
- # Add to the defs
- definitions[name] = type
- # Add on altered columns
- for name, type in altered.items():
- if (primary_key_override and primary_key_override == name) or \
- (not primary_key_override and name in indexes and
- indexes[name]['primary_key']):
- type += " PRIMARY KEY"
- if (name in indexes and indexes[name]['unique'] and
- name not in uniques_deleted):
- type += " UNIQUE"
- definitions[name] = type
- # Add on the new columns
- for name, (type,_) in added.items():
- if (primary_key_override and primary_key_override == name):
- type += " PRIMARY KEY"
- definitions[name] = type
- # Alright, Make the table
- self.execute("CREATE TABLE %s (%s)" % (
- self.quote_name(temp_name),
- ", ".join(["%s %s" % (self.quote_name(cname), ctype) for cname, ctype in definitions.items()]),
- ))
- # Copy over the data
- self._copy_data(table_name, temp_name, renames, added)
- # Delete the old table, move our new one over it
- self.delete_table(table_name)
- self.rename_table(temp_name, table_name)
- # Recreate multi-valued indexes
- # We can't do that before since it's impossible to rename indexes
- # and index name scope is global
- self._make_standalone_indexes(table_name, standalone_indexes, renames=renames, deleted=deleted, uniques_deleted=uniques_deleted)
- self.deferred_sql = [] # prevent double indexing
-
- def _copy_data(self, src, dst, field_renames={}, added={}):
- "Used to copy data into a new table"
- # Make a list of all the fields to select
- cursor = self._get_connection().cursor()
- src_fields = [column_info[0] for column_info in self._get_connection().introspection.get_table_description(cursor, src)]
- dst_fields = [column_info[0] for column_info in self._get_connection().introspection.get_table_description(cursor, dst)]
- src_fields_new = []
- dst_fields_new = []
- for field in src_fields:
- if field in field_renames:
- dst_fields_new.append(self.quote_name(field_renames[field]))
- elif field in dst_fields:
- dst_fields_new.append(self.quote_name(field))
- else:
- continue
- src_fields_new.append(self.quote_name(field))
- for field, (_,default) in added.items():
- if default is not None:
- field = self.quote_name(field)
- src_fields_new.append("%s as %s" % (default, field))
- dst_fields_new.append(field)
- # Copy over the data
- self.execute("INSERT INTO %s (%s) SELECT %s FROM %s;" % (
- self.quote_name(dst),
- ', '.join(dst_fields_new),
- ', '.join(src_fields_new),
- self.quote_name(src),
- ))
-
- def _create_unique(self, table_name, columns):
- self._create_index(table_name, columns, True)
-
- def _create_index(self, table_name, columns, unique=False, index_name=None):
- if index_name is None:
- index_name = '%s_%s' % (table_name, '__'.join(columns))
- self.execute("CREATE %sINDEX %s ON %s(%s);" % (
- unique and "UNIQUE " or "",
- self.quote_name(index_name),
- self.quote_name(table_name),
- ', '.join(self.quote_name(c) for c in columns),
- ))
-
- def _get_standalone_indexes(self, table_name):
- indexes = []
- cursor = self._get_connection().cursor()
- cursor.execute('PRAGMA index_list(%s)' % self.quote_name(table_name))
- # seq, name, unique
- for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:
- cursor.execute('PRAGMA index_info(%s)' % self.quote_name(index))
- info = cursor.fetchall()
- if len(info) == 1 and unique:
- # This index is already specified in the CREATE TABLE columns
- # specification
- continue
- columns = []
- for field in info:
- columns.append(field[2])
- indexes.append((index, columns, unique))
- return indexes
-
- def _make_standalone_indexes(self, table_name, indexes, deleted=[], renames={}, uniques_deleted=[]):
- for index_name, index, unique in indexes:
- columns = []
-
- for name in index:
- # Handle deletion
- if name in deleted:
- columns = []
- break
-
- # Handle renames
- if name in renames:
- name = renames[name]
- columns.append(name)
-
- if columns and (set(columns) != set(uniques_deleted) or not unique):
- self._create_index(table_name, columns, unique, index_name)
-
- def _column_sql_for_create(self, table_name, name, field, explicit_name=True):
- "Given a field and its name, returns the full type for the CREATE TABLE (without unique/pk)"
- field.set_attributes_from_name(name)
- if not explicit_name:
- name = field.db_column
- else:
- field.column = name
- sql = self.column_sql(table_name, name, field, with_name=False, field_prepared=True)
- # Remove keywords we don't want (this should be type only, not constraint)
- if sql:
- sql = sql.replace("PRIMARY KEY", "")
- return sql
-
- def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False):
- """
- Changes a column's SQL definition.
-
- Note that this sqlite3 implementation ignores the ignore_constraints argument.
- The argument is accepted for API compatibility with the generic
- DatabaseOperations.alter_column() method.
- """
- # Change nulls to default if needed
- if not field.null and field.has_default():
- params = {
- "column": self.quote_name(name),
- "table_name": self.quote_name(table_name)
- }
- self._update_nulls_to_default(params, field)
- # Remake the table correctly
- field._suppress_default = True
- self._remake_table(table_name, altered={
- name: self._column_sql_for_create(table_name, name, field, explicit_name),
- })
-
- def delete_column(self, table_name, column_name):
- """
- Deletes a column.
- """
- self._remake_table(table_name, deleted=[column_name])
-
- def rename_column(self, table_name, old, new):
- """
- Renames a column from one name to another.
- """
- self._remake_table(table_name, renames={old: new})
-
- def create_unique(self, table_name, columns):
- """
- Create an unique index on columns
- """
- self._create_unique(table_name, columns)
-
- def delete_unique(self, table_name, columns):
- """
- Delete an unique index
- """
- self._remake_table(table_name, uniques_deleted=columns)
-
- def create_primary_key(self, table_name, columns):
- if not isinstance(columns, (list, tuple)):
- columns = [columns]
- assert len(columns) == 1, "SQLite backend does not support multi-column primary keys"
- self._remake_table(table_name, primary_key_override=columns[0])
-
- # Not implemented this yet.
- def delete_primary_key(self, table_name):
- # By passing True in, we make sure we wipe all existing PKs.
- self._remake_table(table_name, primary_key_override=True)
-
- # No cascades on deletes
- def delete_table(self, table_name, cascade=True):
- generic.DatabaseOperations.delete_table(self, table_name, False)
diff --git a/lib/python2.7/site-packages/south/exceptions.py b/lib/python2.7/site-packages/south/exceptions.py deleted file mode 100644 index f2e772f..0000000 --- a/lib/python2.7/site-packages/south/exceptions.py +++ /dev/null @@ -1,160 +0,0 @@ -from __future__ import print_function - -from traceback import format_exception, format_exc - -class SouthError(RuntimeError): - pass - -class SouthWarning(RuntimeWarning): - pass - -class BrokenMigration(SouthError): - def __init__(self, migration, exc_info): - self.migration = migration - self.exc_info = exc_info - if self.exc_info: - self.traceback = ''.join(format_exception(*self.exc_info)) - else: - try: - self.traceback = format_exc() - except AttributeError: # Python3 when there is no previous exception - self.traceback = None - - def __str__(self): - return ("While loading migration '%(migration)s':\n" - '%(traceback)s' % self.__dict__) - - -class UnknownMigration(BrokenMigration): - def __str__(self): - if not hasattr(self, "traceback"): - self.traceback = "" - return ("Migration '%(migration)s' probably doesn't exist.\n" - '%(traceback)s' % self.__dict__) - - -class InvalidMigrationModule(SouthError): - def __init__(self, application, module): - self.application = application - self.module = module - - def __str__(self): - return ('The migration module specified for %(application)s, %(module)r, is invalid; the parent module does not exist.' % self.__dict__) - - -class NoMigrations(SouthError): - def __init__(self, application): - self.application = application - - def __str__(self): - return "Application '%(application)s' has no migrations." % self.__dict__ - - -class MultiplePrefixMatches(SouthError): - def __init__(self, prefix, matches): - self.prefix = prefix - self.matches = matches - - def __str__(self): - self.matches_list = "\n ".join([str(m) for m in self.matches]) - return ("Prefix '%(prefix)s' matches more than one migration:\n" - " %(matches_list)s") % self.__dict__ - - -class GhostMigrations(SouthError): - def __init__(self, ghosts): - self.ghosts = ghosts - - def __str__(self): - self.ghosts_list = "\n ".join([str(m) for m in self.ghosts]) - return ("\n\n ! These migrations are in the database but not on disk:\n" - " %(ghosts_list)s\n" - " ! I'm not trusting myself; either fix this yourself by fiddling\n" - " ! with the south_migrationhistory table, or pass --delete-ghost-migrations\n" - " ! to South to have it delete ALL of these records (this may not be good).") % self.__dict__ - - -class CircularDependency(SouthError): - def __init__(self, trace): - self.trace = trace - - def __str__(self): - trace = " -> ".join([str(s) for s in self.trace]) - return ("Found circular dependency:\n" - " %s") % trace - - -class InconsistentMigrationHistory(SouthError): - def __init__(self, problems): - self.problems = problems - - def __str__(self): - return ('Inconsistent migration history\n' - 'The following options are available:\n' - ' --merge: will just attempt the migration ignoring any potential dependency conflicts.') - - -class DependsOnHigherMigration(SouthError): - def __init__(self, migration, depends_on): - self.migration = migration - self.depends_on = depends_on - - def __str__(self): - return "Lower migration '%(migration)s' depends on a higher migration '%(depends_on)s' in the same app." % self.__dict__ - - -class DependsOnUnknownMigration(SouthError): - def __init__(self, migration, depends_on): - self.migration = migration - self.depends_on = depends_on - - def __str__(self): - print("Migration '%(migration)s' depends on unknown migration '%(depends_on)s'." % self.__dict__) - - -class DependsOnUnmigratedApplication(SouthError): - def __init__(self, migration, application): - self.migration = migration - self.application = application - - def __str__(self): - return "Migration '%(migration)s' depends on unmigrated application '%(application)s'." % self.__dict__ - - -class FailedDryRun(SouthError): - def __init__(self, migration, exc_info): - self.migration = migration - self.name = migration.name() - self.exc_info = exc_info - self.traceback = ''.join(format_exception(*self.exc_info)) - - def __str__(self): - return (" ! Error found during dry run of '%(name)s'! Aborting.\n" - "%(traceback)s") % self.__dict__ - - -class ORMBaseNotIncluded(SouthError): - """Raised when a frozen model has something in _ormbases which isn't frozen.""" - pass - - -class UnfreezeMeLater(Exception): - """An exception, which tells the ORM unfreezer to postpone this model.""" - pass - - -class ImpossibleORMUnfreeze(SouthError): - """Raised if the ORM can't manage to unfreeze all the models in a linear fashion.""" - pass - -class ConstraintDropped(SouthWarning): - def __init__(self, constraint, table, column=None): - self.table = table - if column: - self.column = ".%s" % column - else: - self.column = "" - self.constraint = constraint - - def __str__(self): - return "Constraint %(constraint)s was dropped from %(table)s%(column)s -- was this intended?" % self.__dict__ diff --git a/lib/python2.7/site-packages/south/hacks/__init__.py b/lib/python2.7/site-packages/south/hacks/__init__.py deleted file mode 100644 index 8f28503..0000000 --- a/lib/python2.7/site-packages/south/hacks/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -The hacks module encapsulates all the horrible things that play with Django -internals in one, evil place. -This top file will automagically expose the correct Hacks class. -""" - -# Currently, these work for 1.0 and 1.1. -from south.hacks.django_1_0 import Hacks - -hacks = Hacks()
\ No newline at end of file diff --git a/lib/python2.7/site-packages/south/hacks/django_1_0.py b/lib/python2.7/site-packages/south/hacks/django_1_0.py deleted file mode 100644 index e4a60c6..0000000 --- a/lib/python2.7/site-packages/south/hacks/django_1_0.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -Hacks for the Django 1.0/1.0.2 releases. -""" - -import django -from django.conf import settings -from django.db.backends.creation import BaseDatabaseCreation -from django.db.models.loading import cache -from django.core import management -from django.core.management.commands.flush import Command as FlushCommand -from django.utils.datastructures import SortedDict - -from south.utils.py3 import string_types - -class SkipFlushCommand(FlushCommand): - def handle_noargs(self, **options): - # no-op to avoid calling flush - return - -class Hacks: - - def set_installed_apps(self, apps): - """ - Sets Django's INSTALLED_APPS setting to be effectively the list passed in. - """ - - # Make sure it's a list. - apps = list(apps) - - # Make sure it contains strings - if apps: - assert isinstance(apps[0], string_types), "The argument to set_installed_apps must be a list of strings." - - # Monkeypatch in! - settings.INSTALLED_APPS, settings.OLD_INSTALLED_APPS = ( - apps, - settings.INSTALLED_APPS, - ) - self._redo_app_cache() - - - def reset_installed_apps(self): - """ - Undoes the effect of set_installed_apps. - """ - settings.INSTALLED_APPS = settings.OLD_INSTALLED_APPS - self._redo_app_cache() - - - def _redo_app_cache(self): - """ - Used to repopulate AppCache after fiddling with INSTALLED_APPS. - """ - cache.loaded = False - cache.handled = set() if django.VERSION >= (1, 6) else {} - cache.postponed = [] - cache.app_store = SortedDict() - cache.app_models = SortedDict() - cache.app_errors = {} - cache._populate() - - - def clear_app_cache(self): - """ - Clears the contents of AppCache to a blank state, so new models - from the ORM can be added. - """ - self.old_app_models, cache.app_models = cache.app_models, {} - - - def unclear_app_cache(self): - """ - Reversed the effects of clear_app_cache. - """ - cache.app_models = self.old_app_models - cache._get_models_cache = {} - - - def repopulate_app_cache(self): - """ - Rebuilds AppCache with the real model definitions. - """ - cache._populate() - - def store_app_cache_state(self): - self.stored_app_cache_state = dict(**cache.__dict__) - - def restore_app_cache_state(self): - cache.__dict__ = self.stored_app_cache_state - - def patch_flush_during_test_db_creation(self): - """ - Patches BaseDatabaseCreation.create_test_db to not flush database - """ - - def patch(f): - def wrapper(*args, **kwargs): - # hold onto the original and replace flush command with a no-op - original_flush_command = management._commands['flush'] - try: - management._commands['flush'] = SkipFlushCommand() - # run create_test_db - return f(*args, **kwargs) - finally: - # unpatch flush back to the original - management._commands['flush'] = original_flush_command - return wrapper - - BaseDatabaseCreation.create_test_db = patch(BaseDatabaseCreation.create_test_db) - diff --git a/lib/python2.7/site-packages/south/introspection_plugins/__init__.py b/lib/python2.7/site-packages/south/introspection_plugins/__init__.py deleted file mode 100644 index 38262b5..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# This module contains built-in introspector plugins for various common -# Django apps. - -# These imports trigger the lower-down files -import south.introspection_plugins.geodjango -import south.introspection_plugins.django_audit_log -import south.introspection_plugins.django_tagging -import south.introspection_plugins.django_taggit -import south.introspection_plugins.django_objectpermissions -import south.introspection_plugins.annoying_autoonetoone - diff --git a/lib/python2.7/site-packages/south/introspection_plugins/annoying_autoonetoone.py b/lib/python2.7/site-packages/south/introspection_plugins/annoying_autoonetoone.py deleted file mode 100644 index d61304f..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/annoying_autoonetoone.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.conf import settings -from south.modelsinspector import add_introspection_rules - -if 'annoying' in settings.INSTALLED_APPS: - try: - from annoying.fields import AutoOneToOneField - except ImportError: - pass - else: - #django-annoying's AutoOneToOneField is essentially a OneToOneField. - add_introspection_rules([], ["^annoying\.fields\.AutoOneToOneField"]) diff --git a/lib/python2.7/site-packages/south/introspection_plugins/django_audit_log.py b/lib/python2.7/site-packages/south/introspection_plugins/django_audit_log.py deleted file mode 100644 index b874428..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/django_audit_log.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -South introspection rules for django-audit-log -""" - -from django.contrib.auth.models import User -from django.conf import settings -from south.modelsinspector import add_introspection_rules - -if "audit_log" in settings.INSTALLED_APPS: - try: - # Try and import the field so we can see if audit_log is available - from audit_log.models import fields - - # Make sure the `to` and `null` parameters will be ignored - rules = [( - (fields.LastUserField,), - [], - { - 'to': ['rel.to', {'default': User}], - 'null': ['null', {'default': True}], - }, - )] - - # Add the rules for the `LastUserField` - add_introspection_rules( - rules, - ['^audit_log\.models\.fields\.LastUserField'], - ) - except ImportError: - pass diff --git a/lib/python2.7/site-packages/south/introspection_plugins/django_objectpermissions.py b/lib/python2.7/site-packages/south/introspection_plugins/django_objectpermissions.py deleted file mode 100644 index 42b353b..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/django_objectpermissions.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -South introspection rules for django-objectpermissions -""" - -from django.conf import settings -from south.modelsinspector import add_ignored_fields - -if 'objectpermissions' in settings.INSTALLED_APPS: - try: - from objectpermissions.models import UserPermissionRelation, GroupPermissionRelation - except ImportError: - pass - else: - add_ignored_fields(["^objectpermissions\.models\.UserPermissionRelation", - "^objectpermissions\.models\.GroupPermissionRelation"]) - diff --git a/lib/python2.7/site-packages/south/introspection_plugins/django_tagging.py b/lib/python2.7/site-packages/south/introspection_plugins/django_tagging.py deleted file mode 100644 index c02e529..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/django_tagging.py +++ /dev/null @@ -1,24 +0,0 @@ -from south.modelsinspector import add_introspection_rules -from django.conf import settings - -if "tagging" in settings.INSTALLED_APPS: - try: - from tagging.fields import TagField - except ImportError: - pass - else: - rules = [ - ( - (TagField, ), - [], - { - "blank": ["blank", {"default": True}], - "max_length": ["max_length", {"default": 255}], - }, - ), - ] - add_introspection_rules(rules, ["^tagging\.fields",]) - -if "tagging_autocomplete" in settings.INSTALLED_APPS: - add_introspection_rules([], ["^tagging_autocomplete\.models\.TagAutocompleteField"]) - diff --git a/lib/python2.7/site-packages/south/introspection_plugins/django_taggit.py b/lib/python2.7/site-packages/south/introspection_plugins/django_taggit.py deleted file mode 100644 index aded23f..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/django_taggit.py +++ /dev/null @@ -1,14 +0,0 @@ -""" -South introspection rules for django-taggit -""" - -from django.conf import settings -from south.modelsinspector import add_ignored_fields - -if 'taggit' in settings.INSTALLED_APPS: - try: - from taggit.managers import TaggableManager - except ImportError: - pass - else: - add_ignored_fields(["^taggit\.managers"]) diff --git a/lib/python2.7/site-packages/south/introspection_plugins/django_timezones.py b/lib/python2.7/site-packages/south/introspection_plugins/django_timezones.py deleted file mode 100644 index d4b573d..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/django_timezones.py +++ /dev/null @@ -1,21 +0,0 @@ -from south.modelsinspector import add_introspection_rules -from django.conf import settings - -if "timezones" in settings.INSTALLED_APPS: - try: - from timezones.fields import TimeZoneField - except ImportError: - pass - else: - rules = [ - ( - (TimeZoneField, ), - [], - { - "blank": ["blank", {"default": True}], - "max_length": ["max_length", {"default": 100}], - }, - ), - ] - add_introspection_rules(rules, ["^timezones\.fields",]) - diff --git a/lib/python2.7/site-packages/south/introspection_plugins/geodjango.py b/lib/python2.7/site-packages/south/introspection_plugins/geodjango.py deleted file mode 100644 index bece1c9..0000000 --- a/lib/python2.7/site-packages/south/introspection_plugins/geodjango.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -GeoDjango introspection rules -""" - -import django -from django.conf import settings - -from south.modelsinspector import add_introspection_rules - -has_gis = "django.contrib.gis" in settings.INSTALLED_APPS - -if has_gis: - # Alright,import the field - from django.contrib.gis.db.models.fields import GeometryField - - # Make some introspection rules - if django.VERSION[0] == 1 and django.VERSION[1] >= 1: - # Django 1.1's gis module renamed these. - rules = [ - ( - (GeometryField, ), - [], - { - "srid": ["srid", {"default": 4326}], - "spatial_index": ["spatial_index", {"default": True}], - "dim": ["dim", {"default": 2}], - "geography": ["geography", {"default": False}], - }, - ), - ] - else: - rules = [ - ( - (GeometryField, ), - [], - { - "srid": ["_srid", {"default": 4326}], - "spatial_index": ["_index", {"default": True}], - "dim": ["_dim", {"default": 2}], - }, - ), - ] - - # Install them - add_introspection_rules(rules, ["^django\.contrib\.gis"])
\ No newline at end of file diff --git a/lib/python2.7/site-packages/south/logger.py b/lib/python2.7/site-packages/south/logger.py deleted file mode 100644 index 2caae3a..0000000 --- a/lib/python2.7/site-packages/south/logger.py +++ /dev/null @@ -1,38 +0,0 @@ -import sys -import logging -from django.conf import settings - -# Create a dummy handler to use for now. -class NullHandler(logging.Handler): - def emit(self, record): - pass - -def get_logger(): - "Attach a file handler to the logger if there isn't one already." - debug_on = getattr(settings, "SOUTH_LOGGING_ON", False) - logging_file = getattr(settings, "SOUTH_LOGGING_FILE", False) - - if debug_on: - if logging_file: - if len(_logger.handlers) < 2: - _logger.addHandler(logging.FileHandler(logging_file)) - _logger.setLevel(logging.DEBUG) - else: - raise IOError("SOUTH_LOGGING_ON is True. You also need a SOUTH_LOGGING_FILE setting.") - - return _logger - -def close_logger(): - "Closes the logger handler for the file, so we can remove the file after a test." - for handler in _logger.handlers: - _logger.removeHandler(handler) - if isinstance(handler, logging.FileHandler): - handler.close() - -def init_logger(): - "Initialize the south logger" - logger = logging.getLogger("south") - logger.addHandler(NullHandler()) - return logger - -_logger = init_logger() diff --git a/lib/python2.7/site-packages/south/management/__init__.py b/lib/python2.7/site-packages/south/management/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/management/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/management/commands/__init__.py b/lib/python2.7/site-packages/south/management/commands/__init__.py deleted file mode 100644 index da218eb..0000000 --- a/lib/python2.7/site-packages/south/management/commands/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ - -# Common framework for syncdb actions - -import copy - -from django.core import management -from django.conf import settings - -# Make sure the template loader cache is fixed _now_ (#448) -import django.template.loaders.app_directories - -from south.hacks import hacks -from south.management.commands.syncdb import Command as SyncCommand - -class MigrateAndSyncCommand(SyncCommand): - """Used for situations where "syncdb" is called by test frameworks.""" - - option_list = copy.deepcopy(SyncCommand.option_list) - - for opt in option_list: - if "--migrate" == opt.get_opt_string(): - opt.default = True - break - -def patch_for_test_db_setup(): - # Load the commands cache - management.get_commands() - # Repoint to the correct version of syncdb - if hasattr(settings, "SOUTH_TESTS_MIGRATE") and not settings.SOUTH_TESTS_MIGRATE: - # point at the core syncdb command when creating tests - # tests should always be up to date with the most recent model structure - management._commands['syncdb'] = 'django.core' - else: - management._commands['syncdb'] = MigrateAndSyncCommand() - # Avoid flushing data migrations. - # http://code.djangoproject.com/ticket/14661 introduced change that flushed custom - # sql during the test database creation (thus flushing the data migrations). - # we patch flush to be no-op during create_test_db, but still allow flushing - # after each test for non-transactional backends. - hacks.patch_flush_during_test_db_creation() diff --git a/lib/python2.7/site-packages/south/management/commands/convert_to_south.py b/lib/python2.7/site-packages/south/management/commands/convert_to_south.py deleted file mode 100644 index 658ed48..0000000 --- a/lib/python2.7/site-packages/south/management/commands/convert_to_south.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -Quick conversion command module. -""" - -from __future__ import print_function - -from optparse import make_option -import sys - -from django.core.management.base import BaseCommand -from django.core.management.color import no_style -from django.conf import settings -from django.db import models -from django.core import management -from django.core.exceptions import ImproperlyConfigured - -from south.migration import Migrations -from south.hacks import hacks -from south.exceptions import NoMigrations - -class Command(BaseCommand): - - option_list = BaseCommand.option_list - if '--verbosity' not in [opt.get_opt_string() for opt in BaseCommand.option_list]: - option_list += ( - make_option('--verbosity', action='store', dest='verbosity', default='1', - type='choice', choices=['0', '1', '2'], - help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), - ) - option_list += ( - make_option('--delete-ghost-migrations', action='store_true', dest='delete_ghosts', default=False, - help="Tells South to delete any 'ghost' migrations (ones in the database but not on disk)."), - make_option('--ignore-ghost-migrations', action='store_true', dest='ignore_ghosts', default=False, - help="Tells South to ignore any 'ghost' migrations (ones in the database but not on disk) and continue to apply new migrations."), - ) - - help = "Quickly converts the named application to use South if it is currently using syncdb." - - def handle(self, app=None, *args, **options): - - # Make sure we have an app - if not app: - print("Please specify an app to convert.") - return - - # See if the app exists - app = app.split(".")[-1] - try: - app_module = models.get_app(app) - except ImproperlyConfigured: - print("There is no enabled application matching '%s'." % app) - return - - # Try to get its list of models - model_list = models.get_models(app_module) - if not model_list: - print("This application has no models; this command is for applications that already have models syncdb'd.") - print("Make some models, and then use ./manage.py schemamigration %s --initial instead." % app) - return - - # Ask South if it thinks it's already got migrations - try: - Migrations(app) - except NoMigrations: - pass - else: - print("This application is already managed by South.") - return - - # Finally! It seems we've got a candidate, so do the two-command trick - verbosity = int(options.get('verbosity', 0)) - management.call_command("schemamigration", app, initial=True, verbosity=verbosity) - - # Now, we need to re-clean and sanitise appcache - hacks.clear_app_cache() - hacks.repopulate_app_cache() - - # And also clear our cached Migration classes - Migrations._clear_cache() - - # Now, migrate - management.call_command( - "migrate", - app, - "0001", - fake=True, - verbosity=verbosity, - ignore_ghosts=options.get("ignore_ghosts", False), - delete_ghosts=options.get("delete_ghosts", False), - ) - - print() - print("App '%s' converted. Note that South assumed the application's models matched the database" % app) - print("(i.e. you haven't changed it since last syncdb); if you have, you should delete the %s/migrations" % app) - print("directory, revert models.py so it matches the database, and try again.") diff --git a/lib/python2.7/site-packages/south/management/commands/datamigration.py b/lib/python2.7/site-packages/south/management/commands/datamigration.py deleted file mode 100644 index c3175e7..0000000 --- a/lib/python2.7/site-packages/south/management/commands/datamigration.py +++ /dev/null @@ -1,139 +0,0 @@ -""" -Data migration creation command -""" - -from __future__ import print_function - -import sys -import os -import re -from optparse import make_option - -try: - set -except NameError: - from sets import Set as set - -from django.core.management.base import BaseCommand -from django.core.management.color import no_style -from django.db import models -from django.conf import settings - -from south.migration import Migrations -from south.exceptions import NoMigrations -from south.creator import freezer - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--freeze', action='append', dest='freeze_list', type='string', - help='Freeze the specified app(s). Provide an app name with each; use the option multiple times for multiple apps'), - make_option('--stdout', action='store_true', dest='stdout', default=False, - help='Print the migration to stdout instead of writing it to a file.'), - ) - help = "Creates a new template data migration for the given app" - usage_str = "Usage: ./manage.py datamigration appname migrationname [--stdout] [--freeze appname]" - - 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) - - def calc_frozen_apps(self, migrations, freeze_list): - """ - Works out, from the current app, settings, and the command line options, - which apps should be frozen. - """ - apps_to_freeze = [] - for to_freeze in freeze_list: - if "." in to_freeze: - self.error("You cannot freeze %r; you must provide an app label, like 'auth' or 'books'." % to_freeze) - # Make sure it's a real app - if not models.get_app(to_freeze): - self.error("You cannot freeze %r; it's not an installed app." % to_freeze) - # OK, it's fine - apps_to_freeze.append(to_freeze) - if getattr(settings, 'SOUTH_AUTO_FREEZE_APP', True): - apps_to_freeze.append(migrations.app_label()) - return apps_to_freeze - - def error(self, message, code=1): - """ - Prints the error, and exits with the given code. - """ - print(message, file=sys.stderr) - sys.exit(code) - - def get_migration_template(self): - return MIGRATION_TEMPLATE - - -MIGRATION_TEMPLATE = """# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import DataMigration -from django.db import models - -class Migration(DataMigration): - - def forwards(self, orm): - "Write your forwards methods here." - # Note: Don't use "from appname.models import ModelName". - # Use orm.ModelName to refer to models in this application, - # and orm['appname.ModelName'] for models in other applications. - - def backwards(self, orm): - "Write your backwards methods here." - - models = %(frozen_models)s - - %(complete_apps)s - symmetrical = True -""" diff --git a/lib/python2.7/site-packages/south/management/commands/graphmigrations.py b/lib/python2.7/site-packages/south/management/commands/graphmigrations.py deleted file mode 100644 index 6ff1e47..0000000 --- a/lib/python2.7/site-packages/south/management/commands/graphmigrations.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Outputs a graphviz dot file of the dependencies. -""" - -from __future__ import print_function - -from optparse import make_option -import re -import textwrap - -from django.core.management.base import BaseCommand -from django.core.management.color import no_style - -from south.migration import Migrations, all_migrations - -class Command(BaseCommand): - - help = "Outputs a GraphViz dot file of all migration dependencies to stdout." - - def handle(self, **options): - - # Resolve dependencies - Migrations.calculate_dependencies() - - colors = [ 'crimson', 'darkgreen', 'darkgoldenrod', 'navy', - 'brown', 'darkorange', 'aquamarine' , 'blueviolet' ] - color_index = 0 - wrapper = textwrap.TextWrapper(width=40) - - print("digraph G {") - - # Group each app in a subgraph - for migrations in all_migrations(): - print(" subgraph %s {" % migrations.app_label()) - print(" node [color=%s];" % colors[color_index]) - for migration in migrations: - # Munge the label - text wrap and change _ to spaces - label = "%s - %s" % ( - migration.app_label(), migration.name()) - label = re.sub(r"_+", " ", label) - label= "\\n".join(wrapper.wrap(label)) - print(' "%s.%s" [label="%s"];' % ( - migration.app_label(), migration.name(), label)) - print(" }") - color_index = (color_index + 1) % len(colors) - - # For every migration, print its links. - for migrations in all_migrations(): - for migration in migrations: - for other in migration.dependencies: - # Added weight tends to keep migrations from the same app - # in vertical alignment - attrs = "[weight=2.0]" - # But the more interesting edges are those between apps - if other.app_label() != migration.app_label(): - attrs = "[style=bold]" - print(' "%s.%s" -> "%s.%s" %s;' % ( - other.app_label(), other.name(), - migration.app_label(), migration.name(), - attrs - )) - - print("}"); diff --git a/lib/python2.7/site-packages/south/management/commands/migrate.py b/lib/python2.7/site-packages/south/management/commands/migrate.py deleted file mode 100644 index 693dbb7..0000000 --- a/lib/python2.7/site-packages/south/management/commands/migrate.py +++ /dev/null @@ -1,264 +0,0 @@ -""" -Migrate management command. -""" - -from __future__ import print_function - -import os.path, re, sys -from functools import reduce -from optparse import make_option - -from django.core.management.base import BaseCommand -from django.conf import settings -from django.utils.importlib import import_module - -from south import migration -from south.migration import Migrations -from south.exceptions import NoMigrations -from south.db import DEFAULT_DB_ALIAS - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--all', action='store_true', dest='all_apps', default=False, - help='Run the specified migration for all apps.'), - make_option('--list', action='store_true', dest='show_list', default=False, - help='List migrations noting those that have been applied'), - make_option('--changes', action='store_true', dest='show_changes', default=False, - help='List changes for migrations'), - make_option('--skip', action='store_true', dest='skip', default=False, - help='Will skip over out-of-order missing migrations'), - make_option('--merge', action='store_true', dest='merge', default=False, - help='Will run out-of-order missing migrations as they are - no rollbacks.'), - make_option('--no-initial-data', action='store_true', dest='no_initial_data', default=False, - help='Skips loading initial data if specified.'), - make_option('--fake', action='store_true', dest='fake', default=False, - help="Pretends to do the migrations, but doesn't actually execute them."), - make_option('--db-dry-run', action='store_true', dest='db_dry_run', default=False, - help="Doesn't execute the SQL generated by the db methods, and doesn't store a record that the migration(s) occurred. Useful to test migrations before applying them."), - make_option('--delete-ghost-migrations', action='store_true', dest='delete_ghosts', default=False, - help="Tells South to delete any 'ghost' migrations (ones in the database but not on disk)."), - make_option('--ignore-ghost-migrations', action='store_true', dest='ignore_ghosts', default=False, - help="Tells South to ignore any 'ghost' migrations (ones in the database but not on disk) and continue to apply new migrations."), - make_option('--noinput', action='store_false', dest='interactive', default=True, - help='Tells Django to NOT prompt the user for input of any kind.'), - make_option('--database', action='store', dest='database', - default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. ' - 'Defaults to the "default" database.'), - ) - if '--verbosity' not in [opt.get_opt_string() for opt in BaseCommand.option_list]: - option_list += ( - make_option('--verbosity', action='store', dest='verbosity', default='1', - type='choice', choices=['0', '1', '2'], - help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), - ) - help = "Runs migrations for all apps." - args = "[appname] [migrationname|zero] [--all] [--list] [--skip] [--merge] [--no-initial-data] [--fake] [--db-dry-run] [--database=dbalias]" - - def handle(self, app=None, target=None, skip=False, merge=False, backwards=False, fake=False, db_dry_run=False, show_list=False, show_changes=False, database=DEFAULT_DB_ALIAS, delete_ghosts=False, ignore_ghosts=False, **options): - - # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb - # This code imports any module named 'management' in INSTALLED_APPS. - # The 'management' module is the preferred way of listening to post_syncdb - # signals, and since we're sending those out with create_table migrations, - # we need apps to behave correctly. - for app_name in settings.INSTALLED_APPS: - try: - import_module('.management', app_name) - except ImportError as exc: - msg = exc.args[0] - if not msg.startswith('No module named') or 'management' not in msg: - raise - # END DJANGO DUPE CODE - - # if all_apps flag is set, shift app over to target - if options.get('all_apps', False): - target = app - app = None - - # Migrate each app - if app: - try: - apps = [Migrations(app)] - except NoMigrations: - print("The app '%s' does not appear to use migrations." % app) - print("./manage.py migrate " + self.args) - return - else: - apps = list(migration.all_migrations()) - - # Do we need to show the list of migrations? - if show_list and apps: - list_migrations(apps, database, **options) - - if show_changes and apps: - show_migration_changes(apps) - - if not (show_list or show_changes): - - for app in apps: - result = migration.migrate_app( - app, - target_name = target, - fake = fake, - db_dry_run = db_dry_run, - verbosity = int(options.get('verbosity', 0)), - interactive = options.get('interactive', True), - load_initial_data = not options.get('no_initial_data', False), - merge = merge, - skip = skip, - database = database, - delete_ghosts = delete_ghosts, - ignore_ghosts = ignore_ghosts, - ) - if result is False: - sys.exit(1) # Migration failed, so the command fails. - - -def list_migrations(apps, database = DEFAULT_DB_ALIAS, **options): - """ - Prints a list of all available migrations, and which ones are currently applied. - Accepts a list of Migrations instances. - """ - from south.models import MigrationHistory - applied_migrations = MigrationHistory.objects.filter(app_name__in=[app.app_label() for app in apps]) - if database != DEFAULT_DB_ALIAS: - applied_migrations = applied_migrations.using(database) - applied_migrations_lookup = dict(('%s.%s' % (mi.app_name, mi.migration), mi) for mi in applied_migrations) - - print() - for app in apps: - print(" " + app.app_label()) - # Get the migrations object - for migration in app: - full_name = migration.app_label() + "." + migration.name() - if full_name in applied_migrations_lookup: - applied_migration = applied_migrations_lookup[full_name] - print(format_migration_list_item(migration.name(), applied=applied_migration.applied, **options)) - else: - print(format_migration_list_item(migration.name(), applied=False, **options)) - print() - -def show_migration_changes(apps): - """ - Prints a list of all available migrations, and which ones are currently applied. - Accepts a list of Migrations instances. - - Much simpler, less clear, and much less robust version: - grep "ing " migrations/*.py - """ - for app in apps: - print(app.app_label()) - # Get the migrations objects - migrations = [migration for migration in app] - # we use reduce to compare models in pairs, not to generate a value - reduce(diff_migrations, migrations) - -def format_migration_list_item(name, applied=True, **options): - if applied: - if int(options.get('verbosity')) >= 2: - return ' (*) %-80s (applied %s)' % (name, applied) - else: - return ' (*) %s' % name - else: - return ' ( ) %s' % name - -def diff_migrations(migration1, migration2): - - def model_name(models, model): - return models[model].get('Meta', {}).get('object_name', model) - - def field_name(models, model, field): - return '%s.%s' % (model_name(models, model), field) - - print(" " + migration2.name()) - - models1 = migration1.migration_class().models - models2 = migration2.migration_class().models - - # find new models - for model in models2.keys(): - if not model in models1.keys(): - print(' added model %s' % model_name(models2, model)) - - # find removed models - for model in models1.keys(): - if not model in models2.keys(): - print(' removed model %s' % model_name(models1, model)) - - # compare models - for model in models1: - if model in models2: - - # find added fields - for field in models2[model]: - if not field in models1[model]: - print(' added field %s' % field_name(models2, model, field)) - - # find removed fields - for field in models1[model]: - if not field in models2[model]: - print(' removed field %s' % field_name(models1, model, field)) - - # compare fields - for field in models1[model]: - if field in models2[model]: - - name = field_name(models1, model, field) - - # compare field attributes - field_value1 = models1[model][field] - field_value2 = models2[model][field] - - # if a field has become a class, or vice versa - if type(field_value1) != type(field_value2): - print(' type of %s changed from %s to %s' % ( - name, field_value1, field_value2)) - - # if class - elif isinstance(field_value1, dict): - # print ' %s is a class' % name - pass - - # else regular field - else: - - type1, attr_list1, field_attrs1 = models1[model][field] - type2, attr_list2, field_attrs2 = models2[model][field] - - if type1 != type2: - print(' %s type changed from %s to %s' % ( - name, type1, type2)) - - if attr_list1 != []: - print(' %s list %s is not []' % ( - name, attr_list1)) - if attr_list2 != []: - print(' %s list %s is not []' % ( - name, attr_list2)) - if attr_list1 != attr_list2: - print(' %s list changed from %s to %s' % ( - name, attr_list1, attr_list2)) - - # find added field attributes - for attr in field_attrs2: - if not attr in field_attrs1: - print(' added %s attribute %s=%s' % ( - name, attr, field_attrs2[attr])) - - # find removed field attributes - for attr in field_attrs1: - if not attr in field_attrs2: - print(' removed attribute %s(%s=%s)' % ( - name, attr, field_attrs1[attr])) - - # compare field attributes - for attr in field_attrs1: - if attr in field_attrs2: - - value1 = field_attrs1[attr] - value2 = field_attrs2[attr] - if value1 != value2: - print(' %s attribute %s changed from %s to %s' % ( - name, attr, value1, value2)) - - return migration2 diff --git a/lib/python2.7/site-packages/south/management/commands/migrationcheck.py b/lib/python2.7/site-packages/south/management/commands/migrationcheck.py deleted file mode 100644 index f498d0b..0000000 --- a/lib/python2.7/site-packages/south/management/commands/migrationcheck.py +++ /dev/null @@ -1,67 +0,0 @@ -from django.core.exceptions import ImproperlyConfigured -from django.core.management import call_command, CommandError -from django.core.management.base import BaseCommand -from django.conf import settings -from django.db.models import loading -from django.test import simple - -from south.migration import Migrations -from south.exceptions import NoMigrations -from south.hacks import hacks - -class Command(BaseCommand): - help = "Runs migrations for each app in turn, detecting missing depends_on values." - usage_str = "Usage: ./manage.py migrationcheck" - - def handle(self, check_app_name=None, **options): - runner = simple.DjangoTestSuiteRunner(verbosity=0) - err_msg = "Failed to migrate %s; see output for hints at missing dependencies:\n" - hacks.patch_flush_during_test_db_creation() - failures = 0 - if check_app_name is None: - app_names = settings.INSTALLED_APPS - else: - app_names = [check_app_name] - for app_name in app_names: - app_label = app_name.split(".")[-1] - if app_name == 'south': - continue - - try: - Migrations(app_name) - except (NoMigrations, ImproperlyConfigured): - continue - app = loading.get_app(app_label) - - verbosity = int(options.get('verbosity', 1)) - if verbosity >= 1: - self.stderr.write("processing %s\n" % app_name) - - old_config = runner.setup_databases() - try: - call_command('migrate', app_label, noinput=True, verbosity=verbosity) - for model in loading.get_models(app): - dummy = model._default_manager.exists() - except (KeyboardInterrupt, SystemExit): - raise - except Exception as e: - failures += 1 - if verbosity >= 1: - self.stderr.write(err_msg % app_name) - self.stderr.write("%s\n" % e) - finally: - runner.teardown_databases(old_config) - if failures > 0: - raise CommandError("Missing depends_on found in %s app(s)." % failures) - self.stderr.write("No missing depends_on found.\n") -# -#for each app: -# start with blank db. -# syncdb only south (and contrib?) -# -# migrate a single app all the way up. any errors is missing depends_on. -# for all models of that app, try the default manager: -# from django.db.models import loading -# for m in loading.get_models(loading.get_app('a')): -# m._default_manager.exists() -# Any error is also a missing depends on. diff --git a/lib/python2.7/site-packages/south/management/commands/schemamigration.py b/lib/python2.7/site-packages/south/management/commands/schemamigration.py deleted file mode 100644 index efd4266..0000000 --- a/lib/python2.7/site-packages/south/management/commands/schemamigration.py +++ /dev/null @@ -1,229 +0,0 @@ -""" -Startmigration command, version 2. -""" - -from __future__ import print_function - -import sys -import os -import re -import string -import random -import inspect -from optparse import make_option - -try: - set -except NameError: - from sets import Set as set - -from django.core.management.base import BaseCommand -from django.core.management.color import no_style -from django.core.exceptions import ImproperlyConfigured -from django.db import models -from django.conf import settings - -from south.migration import Migrations, migrate_app -from south.models import MigrationHistory -from south.exceptions import NoMigrations -from south.creator import changes, actions, freezer -from south.management.commands.datamigration import Command as DataCommand - -class Command(DataCommand): - option_list = DataCommand.option_list + ( - make_option('--add-model', action='append', dest='added_model_list', type='string', - help='Generate a Create Table migration for the specified model. Add multiple models to this migration with subsequent --add-model parameters.'), - make_option('--add-field', action='append', dest='added_field_list', type='string', - help='Generate an Add Column migration for the specified modelname.fieldname - you can use this multiple times to add more than one column.'), - make_option('--add-index', action='append', dest='added_index_list', type='string', - help='Generate an Add Index migration for the specified modelname.fieldname - you can use this multiple times to add more than one column.'), - make_option('--initial', action='store_true', dest='initial', default=False, - help='Generate the initial schema for the app.'), - make_option('--auto', action='store_true', dest='auto', default=False, - help='Attempt to automatically detect differences from the last migration.'), - make_option('--empty', action='store_true', dest='empty', default=False, - help='Make a blank migration.'), - make_option('--update', action='store_true', dest='update', default=False, - help='Update the most recent migration instead of creating a new one. Rollback this migration if it is already applied.'), - ) - help = "Creates a new template schema migration for the given app" - usage_str = "Usage: ./manage.py schemamigration appname migrationname [--empty] [--initial] [--auto] [--add-model ModelName] [--add-field ModelName.field_name] [--stdout]" - - 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) - - def get_migration_template(self): - return MIGRATION_TEMPLATE - - -MIGRATION_TEMPLATE = """# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): -%(forwards)s - - def backwards(self, orm): -%(backwards)s - - models = %(frozen_models)s - - %(complete_apps)s""" diff --git a/lib/python2.7/site-packages/south/management/commands/startmigration.py b/lib/python2.7/site-packages/south/management/commands/startmigration.py deleted file mode 100644 index e4fcf45..0000000 --- a/lib/python2.7/site-packages/south/management/commands/startmigration.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Now-obsolete startmigration command. -""" - -from __future__ import print_function - -from optparse import make_option - -from django.core.management.base import BaseCommand -from django.core.management.color import no_style - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--model', action='append', dest='added_model_list', type='string', - help='Generate a Create Table migration for the specified model. Add multiple models to this migration with subsequent --add-model parameters.'), - make_option('--add-field', action='append', dest='added_field_list', type='string', - help='Generate an Add Column migration for the specified modelname.fieldname - you can use this multiple times to add more than one column.'), - make_option('--add-index', action='append', dest='added_index_list', type='string', - help='Generate an Add Index migration for the specified modelname.fieldname - you can use this multiple times to add more than one column.'), - make_option('--initial', action='store_true', dest='initial', default=False, - help='Generate the initial schema for the app.'), - make_option('--auto', action='store_true', dest='auto', default=False, - help='Attempt to automatically detect differences from the last migration.'), - make_option('--freeze', action='append', dest='freeze_list', type='string', - help='Freeze the specified model(s). Pass in either an app name (to freeze the whole app) or a single model, as appname.modelname.'), - make_option('--stdout', action='store_true', dest='stdout', default=False, - help='Print the migration to stdout instead of writing it to a file.'), - ) - help = "Deprecated command" - - def handle(self, app=None, name="", added_model_list=None, added_field_list=None, initial=False, freeze_list=None, auto=False, stdout=False, added_index_list=None, **options): - - print("The 'startmigration' command is now deprecated; please use the new 'schemamigration' and 'datamigration' commands.") diff --git a/lib/python2.7/site-packages/south/management/commands/syncdb.py b/lib/python2.7/site-packages/south/management/commands/syncdb.py deleted file mode 100644 index 17fc22c..0000000 --- a/lib/python2.7/site-packages/south/management/commands/syncdb.py +++ /dev/null @@ -1,115 +0,0 @@ -""" -Overridden syncdb command -""" - -from __future__ import print_function - -import sys -from optparse import make_option - -from django.core.management.base import NoArgsCommand, BaseCommand -from django.core.management.color import no_style -from django.utils.datastructures import SortedDict -from django.core.management.commands import syncdb -from django.conf import settings -from django.db import models -from django.db.models.loading import cache -from django.core import management - -from south.db import dbs -from south import migration -from south.exceptions import NoMigrations - -def get_app_label(app): - return '.'.join( app.__name__.split('.')[0:-1] ) - -class Command(NoArgsCommand): - option_list = syncdb.Command.option_list + ( - make_option('--migrate', action='store_true', dest='migrate', default=False, - help='Tells South to also perform migrations after the sync. Default for during testing, and other internal calls.'), - make_option('--all', action='store_true', dest='migrate_all', default=False, - help='Makes syncdb work on all apps, even migrated ones. Be careful!'), - ) - if '--verbosity' not in [opt.get_opt_string() for opt in syncdb.Command.option_list]: - option_list += ( - make_option('--verbosity', action='store', dest='verbosity', default='1', - type='choice', choices=['0', '1', '2'], - help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), - ) - help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created, except those which use migrations." - - def handle_noargs(self, migrate_all=False, **options): - - # Import the 'management' module within each installed app, to register - # dispatcher events. - # This is copied from Django, to fix bug #511. - try: - from django.utils.importlib import import_module - except ImportError: - pass # TODO: Remove, only for Django1.0 - else: - for app_name in settings.INSTALLED_APPS: - try: - import_module('.management', app_name) - except ImportError as exc: - msg = exc.args[0] - if not msg.startswith('No module named') or 'management' not in msg: - raise - - # Work out what uses migrations and so doesn't need syncing - apps_needing_sync = [] - apps_migrated = [] - for app in models.get_apps(): - app_label = get_app_label(app) - if migrate_all: - apps_needing_sync.append(app_label) - else: - try: - migrations = migration.Migrations(app_label) - except NoMigrations: - # It needs syncing - apps_needing_sync.append(app_label) - else: - # This is a migrated app, leave it - apps_migrated.append(app_label) - verbosity = int(options.get('verbosity', 0)) - - # Run syncdb on only the ones needed - if verbosity: - print("Syncing...") - - old_installed, settings.INSTALLED_APPS = settings.INSTALLED_APPS, apps_needing_sync - old_app_store, cache.app_store = cache.app_store, SortedDict([ - (k, v) for (k, v) in cache.app_store.items() - if get_app_label(k) in apps_needing_sync - ]) - - # This will allow the setting of the MySQL storage engine, for example. - for db in dbs.values(): - db.connection_init() - - # OK, run the actual syncdb - syncdb.Command().execute(**options) - - settings.INSTALLED_APPS = old_installed - cache.app_store = old_app_store - - # Migrate if needed - if options.get('migrate', True): - if verbosity: - print("Migrating...") - # convert from store_true to store_false - options['no_initial_data'] = not options.get('load_initial_data', True) - management.call_command('migrate', **options) - - # Be obvious about what we did - if verbosity: - print("\nSynced:\n > %s" % "\n > ".join(apps_needing_sync)) - - if options.get('migrate', True): - if verbosity: - print("\nMigrated:\n - %s" % "\n - ".join(apps_migrated)) - else: - if verbosity: - print("\nNot synced (use migrations):\n - %s" % "\n - ".join(apps_migrated)) - print("(use ./manage.py migrate to migrate these)") diff --git a/lib/python2.7/site-packages/south/management/commands/test.py b/lib/python2.7/site-packages/south/management/commands/test.py deleted file mode 100644 index 9901786..0000000 --- a/lib/python2.7/site-packages/south/management/commands/test.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.core.management.commands import test - -from south.management.commands import patch_for_test_db_setup - -class Command(test.Command): - def handle(self, *args, **kwargs): - patch_for_test_db_setup() - super(Command, self).handle(*args, **kwargs) diff --git a/lib/python2.7/site-packages/south/management/commands/testserver.py b/lib/python2.7/site-packages/south/management/commands/testserver.py deleted file mode 100644 index 3c3c4b5..0000000 --- a/lib/python2.7/site-packages/south/management/commands/testserver.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.core.management.commands import testserver - -from south.management.commands import patch_for_test_db_setup - -class Command(testserver.Command): - def handle(self, *args, **kwargs): - patch_for_test_db_setup() - super(Command, self).handle(*args, **kwargs) diff --git a/lib/python2.7/site-packages/south/migration/__init__.py b/lib/python2.7/site-packages/south/migration/__init__.py deleted file mode 100644 index 1d91ddf..0000000 --- a/lib/python2.7/site-packages/south/migration/__init__.py +++ /dev/null @@ -1,235 +0,0 @@ -""" -Main migration logic. -""" - -from __future__ import print_function - -import sys - -from django.core.exceptions import ImproperlyConfigured - -import south.db -from south import exceptions -from south.models import MigrationHistory -from south.db import db, DEFAULT_DB_ALIAS -from south.migration.migrators import (Backwards, Forwards, - DryRunMigrator, FakeMigrator, - LoadInitialDataMigrator) -from south.migration.base import Migration, Migrations -from south.migration.utils import SortedSet -from south.migration.base import all_migrations -from south.signals import pre_migrate, post_migrate - - -def to_apply(forwards, done): - return [m for m in forwards if m not in done] - -def to_unapply(backwards, done): - return [m for m in backwards if m in done] - -def problems(pending, done): - last = None - if not pending: - raise StopIteration() - for migration in pending: - if migration in done: - last = migration - continue - if last and migration not in done: - yield last, migration - -def forwards_problems(pending, done, verbosity): - """ - Takes the list of linearised pending migrations, and the set of done ones, - and returns the list of problems, if any. - """ - return inner_problem_check(problems(reversed(pending), done), done, verbosity) - -def backwards_problems(pending, done, verbosity): - return inner_problem_check(problems(pending, done), done, verbosity) - -def inner_problem_check(problems, done, verbosity): - "Takes a set of possible problems and gets the actual issues out of it." - result = [] - for last, migration in problems: - checked = set([]) - # 'Last' is the last applied migration. Step back from it until we - # either find nothing wrong, or we find something. - to_check = list(last.dependencies) - while to_check: - checking = to_check.pop() - if checking in checked: - continue - checked.add(checking) - - if checking not in done: - # That's bad. Error. - if verbosity: - print((" ! Migration %s should not have been applied " - "before %s but was." % (last, checking))) - result.append((last, checking)) - else: - to_check.extend(checking.dependencies) - return result - -def check_migration_histories(histories, delete_ghosts=False, ignore_ghosts=False): - "Checks that there's no 'ghost' migrations in the database." - exists = SortedSet() - ghosts = [] - for h in histories: - try: - m = h.get_migration() - m.migration() - except exceptions.UnknownMigration: - ghosts.append(h) - except ImproperlyConfigured: - pass # Ignore missing applications - else: - exists.add(m) - if ghosts: - # They may want us to delete ghosts. - if delete_ghosts: - for h in ghosts: - h.delete() - elif not ignore_ghosts: - raise exceptions.GhostMigrations(ghosts) - return exists - -def get_dependencies(target, migrations): - forwards = list - backwards = list - if target is None: - backwards = migrations[0].backwards_plan - else: - forwards = target.forwards_plan - # When migrating backwards we want to remove up to and - # including the next migration up in this app (not the next - # one, that includes other apps) - migration_before_here = target.next() - if migration_before_here: - backwards = migration_before_here.backwards_plan - return forwards, backwards - -def get_direction(target, applied, migrations, verbosity, interactive): - # Get the forwards and reverse dependencies for this target - forwards, backwards = get_dependencies(target, migrations) - # Is the whole forward branch applied? - problems = None - forwards = forwards() - workplan = to_apply(forwards, applied) - if not workplan: - # If they're all applied, we only know it's not backwards - direction = None - else: - # If the remaining migrations are strictly a right segment of - # the forwards trace, we just need to go forwards to our - # target (and check for badness) - problems = forwards_problems(forwards, applied, verbosity) - direction = Forwards(verbosity=verbosity, interactive=interactive) - if not problems: - # What about the whole backward trace then? - backwards = backwards() - missing_backwards = to_apply(backwards, applied) - if missing_backwards != backwards: - # If what's missing is a strict left segment of backwards (i.e. - # all the higher migrations) then we need to go backwards - workplan = to_unapply(backwards, applied) - problems = backwards_problems(backwards, applied, verbosity) - direction = Backwards(verbosity=verbosity, interactive=interactive) - return direction, problems, workplan - -def get_migrator(direction, db_dry_run, fake, load_initial_data): - if not direction: - return direction - if db_dry_run: - direction = DryRunMigrator(migrator=direction, ignore_fail=False) - elif fake: - direction = FakeMigrator(migrator=direction) - elif load_initial_data: - direction = LoadInitialDataMigrator(migrator=direction) - return direction - -def get_unapplied_migrations(migrations, applied_migrations): - applied_migration_names = ['%s.%s' % (mi.app_name,mi.migration) for mi in applied_migrations] - - for migration in migrations: - is_applied = '%s.%s' % (migration.app_label(), migration.name()) in applied_migration_names - if not is_applied: - yield migration - -def migrate_app(migrations, target_name=None, merge=False, fake=False, db_dry_run=False, yes=False, verbosity=0, load_initial_data=False, skip=False, database=DEFAULT_DB_ALIAS, delete_ghosts=False, ignore_ghosts=False, interactive=False): - app_label = migrations.app_label() - - verbosity = int(verbosity) - # Fire off the pre-migrate signal - pre_migrate.send(None, app=app_label, verbosity=verbosity, interactive=verbosity, db=database) - - # If there aren't any, quit quizically - if not migrations: - print("? You have no migrations for the '%s' app. You might want some." % app_label) - return - - # Load the entire dependency graph - Migrations.calculate_dependencies() - - # Check there's no strange ones in the database - applied_all = MigrationHistory.objects.filter(applied__isnull=False).order_by('applied').using(database) - applied = applied_all.filter(app_name=app_label).using(database) - south.db.db = south.db.dbs[database] - Migrations.invalidate_all_modules() - - south.db.db.debug = (verbosity > 1) - - if target_name == 'current-1': - if applied.count() > 1: - previous_migration = applied[applied.count() - 2] - if verbosity: - print('previous_migration: %s (applied: %s)' % (previous_migration.migration, previous_migration.applied)) - target_name = previous_migration.migration - else: - if verbosity: - print('previous_migration: zero') - target_name = 'zero' - elif target_name == 'current+1': - try: - first_unapplied_migration = get_unapplied_migrations(migrations, applied).next() - target_name = first_unapplied_migration.name() - except StopIteration: - target_name = None - - applied_all = check_migration_histories(applied_all, delete_ghosts, ignore_ghosts) - - # Guess the target_name - target = migrations.guess_migration(target_name) - if verbosity: - if target_name not in ('zero', None) and target.name() != target_name: - print(" - Soft matched migration %s to %s." % (target_name, - target.name())) - print("Running migrations for %s:" % app_label) - - # Get the forwards and reverse dependencies for this target - direction, problems, workplan = get_direction(target, applied_all, migrations, - verbosity, interactive) - if problems and not (merge or skip): - raise exceptions.InconsistentMigrationHistory(problems) - - # Perform the migration - migrator = get_migrator(direction, db_dry_run, fake, load_initial_data) - if migrator: - migrator.print_title(target) - success = migrator.migrate_many(target, workplan, database) - # Finally, fire off the post-migrate signal - if success: - post_migrate.send(None, app=app_label, verbosity=verbosity, interactive=verbosity, db=database) - else: - if verbosity: - # Say there's nothing. - print('- Nothing to migrate.') - # If we have initial data enabled, and we're at the most recent - # migration, do initial data. - # Note: We use a fake Forwards() migrator here. It's never used really. - if load_initial_data: - migrator = LoadInitialDataMigrator(migrator=Forwards(verbosity=verbosity)) - migrator.load_initial_data(target, db=database) - # Send signal. - post_migrate.send(None, app=app_label, verbosity=verbosity, interactive=verbosity, db=database) diff --git a/lib/python2.7/site-packages/south/migration/base.py b/lib/python2.7/site-packages/south/migration/base.py deleted file mode 100644 index 8bd6a5a..0000000 --- a/lib/python2.7/site-packages/south/migration/base.py +++ /dev/null @@ -1,440 +0,0 @@ -from __future__ import print_function - -from collections import deque -import datetime -from imp import reload -import os -import re -import sys - -from django.core.exceptions import ImproperlyConfigured -from django.db import models -from django.conf import settings -from django.utils import importlib - -from south import exceptions -from south.migration.utils import depends, dfs, flatten, get_app_label -from south.orm import FakeORM -from south.utils import memoize, ask_for_it_by_name, datetime_utils -from south.migration.utils import app_label_to_app_module -from south.utils.py3 import string_types, with_metaclass - -def all_migrations(applications=None): - """ - Returns all Migrations for all `applications` that are migrated. - """ - if applications is None: - applications = models.get_apps() - for model_module in applications: - # The app they've passed is the models module - go up one level - app_path = ".".join(model_module.__name__.split(".")[:-1]) - app = ask_for_it_by_name(app_path) - try: - yield Migrations(app) - except exceptions.NoMigrations: - pass - - -def application_to_app_label(application): - "Works out the app label from either the app label, the app name, or the module" - if isinstance(application, string_types): - app_label = application.split('.')[-1] - else: - app_label = application.__name__.split('.')[-1] - return app_label - - -class MigrationsMetaclass(type): - - """ - Metaclass which ensures there is only one instance of a Migrations for - any given app. - """ - - def __init__(self, name, bases, dict): - super(MigrationsMetaclass, self).__init__(name, bases, dict) - self.instances = {} - - def __call__(self, application, **kwds): - - app_label = application_to_app_label(application) - - # If we don't already have an instance, make one - if app_label not in self.instances: - self.instances[app_label] = super(MigrationsMetaclass, self).__call__(app_label_to_app_module(app_label), **kwds) - - return self.instances[app_label] - - def _clear_cache(self): - "Clears the cache of Migration objects." - self.instances = {} - - -class Migrations(with_metaclass(MigrationsMetaclass, list)): - """ - Holds a list of Migration objects for a particular app. - """ - - if getattr(settings, "SOUTH_USE_PYC", False): - MIGRATION_FILENAME = re.compile(r'(?!__init__)' # Don't match __init__.py - r'[0-9a-zA-Z_]*' # Don't match dotfiles, or names with dots/invalid chars in them - r'(\.pyc?)?$') # Match .py or .pyc files, or module dirs - else: - MIGRATION_FILENAME = re.compile(r'(?!__init__)' # Don't match __init__.py - r'[0-9a-zA-Z_]*' # Don't match dotfiles, or names with dots/invalid chars in them - r'(\.py)?$') # Match only .py files, or module dirs - - def __init__(self, application, force_creation=False, verbose_creation=True): - "Constructor. Takes the module of the app, NOT its models (like get_app returns)" - self._cache = {} - self.set_application(application, force_creation, verbose_creation) - - def create_migrations_directory(self, verbose=True): - "Given an application, ensures that the migrations directory is ready." - migrations_dir = self.migrations_dir() - # Make the directory if it's not already there - if not os.path.isdir(migrations_dir): - if verbose: - print("Creating migrations directory at '%s'..." % migrations_dir) - os.mkdir(migrations_dir) - # Same for __init__.py - init_path = os.path.join(migrations_dir, "__init__.py") - if not os.path.isfile(init_path): - # Touch the init py file - if verbose: - print("Creating __init__.py in '%s'..." % migrations_dir) - open(init_path, "w").close() - - def migrations_dir(self): - """ - Returns the full path of the migrations directory. - If it doesn't exist yet, returns where it would exist, based on the - app's migrations module (defaults to app.migrations) - """ - module_path = self.migrations_module() - try: - module = importlib.import_module(module_path) - except ImportError: - # There's no migrations module made yet; guess! - try: - parent = importlib.import_module(".".join(module_path.split(".")[:-1])) - except ImportError: - # The parent doesn't even exist, that's an issue. - raise exceptions.InvalidMigrationModule( - application = self.application.__name__, - module = module_path, - ) - else: - # Good guess. - return os.path.join(os.path.dirname(parent.__file__), module_path.split(".")[-1]) - else: - # Get directory directly - return os.path.dirname(module.__file__) - - def migrations_module(self): - "Returns the module name of the migrations module for this" - app_label = application_to_app_label(self.application) - if hasattr(settings, "SOUTH_MIGRATION_MODULES"): - if app_label in settings.SOUTH_MIGRATION_MODULES: - # There's an override. - return settings.SOUTH_MIGRATION_MODULES[app_label] - return self._application.__name__ + '.migrations' - - def get_application(self): - return self._application - - def set_application(self, application, force_creation=False, verbose_creation=True): - """ - Called when the application for this Migrations is set. - Imports the migrations module object, and throws a paddy if it can't. - """ - self._application = application - if not hasattr(application, 'migrations'): - try: - module = importlib.import_module(self.migrations_module()) - self._migrations = application.migrations = module - except ImportError: - if force_creation: - self.create_migrations_directory(verbose_creation) - module = importlib.import_module(self.migrations_module()) - self._migrations = application.migrations = module - else: - raise exceptions.NoMigrations(application) - self._load_migrations_module(application.migrations) - - application = property(get_application, set_application) - - def _load_migrations_module(self, module): - self._migrations = module - filenames = [] - dirname = self.migrations_dir() - for f in os.listdir(dirname): - if self.MIGRATION_FILENAME.match(os.path.basename(f)): - full_path = os.path.join(dirname, f) - # If it's a .pyc file, only append if the .py isn't already around - if f.endswith(".pyc") and (os.path.isfile(full_path[:-1])): - continue - # If it's a module directory, only append if it contains __init__.py[c]. - if os.path.isdir(full_path): - if not (os.path.isfile(os.path.join(full_path, "__init__.py")) or \ - (getattr(settings, "SOUTH_USE_PYC", False) and \ - os.path.isfile(os.path.join(full_path, "__init__.pyc")))): - continue - filenames.append(f) - filenames.sort() - self.extend(self.migration(f) for f in filenames) - - def migration(self, filename): - name = Migration.strip_filename(filename) - if name not in self._cache: - self._cache[name] = Migration(self, name) - return self._cache[name] - - def __getitem__(self, value): - if isinstance(value, string_types): - return self.migration(value) - return super(Migrations, self).__getitem__(value) - - def _guess_migration(self, prefix): - prefix = Migration.strip_filename(prefix) - matches = [m for m in self if m.name().startswith(prefix)] - if len(matches) == 1: - return matches[0] - elif len(matches) > 1: - raise exceptions.MultiplePrefixMatches(prefix, matches) - else: - raise exceptions.UnknownMigration(prefix, None) - - def guess_migration(self, target_name): - if target_name == 'zero' or not self: - return - elif target_name is None: - return self[-1] - else: - return self._guess_migration(prefix=target_name) - - def app_label(self): - return self._application.__name__.split('.')[-1] - - def full_name(self): - return self._migrations.__name__ - - @classmethod - def calculate_dependencies(cls, force=False): - "Goes through all the migrations, and works out the dependencies." - if getattr(cls, "_dependencies_done", False) and not force: - return - for migrations in all_migrations(): - for migration in migrations: - migration.calculate_dependencies() - cls._dependencies_done = True - - @staticmethod - def invalidate_all_modules(): - "Goes through all the migrations, and invalidates all cached modules." - for migrations in all_migrations(): - for migration in migrations: - migration.invalidate_module() - - def next_filename(self, name): - "Returns the fully-formatted filename of what a new migration 'name' would be" - highest_number = 0 - for migration in self: - try: - number = int(migration.name().split("_")[0]) - highest_number = max(highest_number, number) - except ValueError: - pass - # Work out the new filename - return "%04i_%s.py" % ( - highest_number + 1, - name, - ) - - -class Migration(object): - - """ - Class which represents a particular migration file on-disk. - """ - - def __init__(self, migrations, filename): - """ - Returns the migration class implied by 'filename'. - """ - self.migrations = migrations - self.filename = filename - self.dependencies = set() - self.dependents = set() - - def __str__(self): - return self.app_label() + ':' + self.name() - - def __repr__(self): - return '<Migration: %s>' % str(self) - - def __eq__(self, other): - return self.app_label() == other.app_label() and self.name() == other.name() - - def __hash__(self): - return hash(str(self)) - - def app_label(self): - return self.migrations.app_label() - - @staticmethod - def strip_filename(filename): - return os.path.splitext(os.path.basename(filename))[0] - - def name(self): - return self.strip_filename(os.path.basename(self.filename)) - - def full_name(self): - return self.migrations.full_name() + '.' + self.name() - - def migration(self): - "Tries to load the actual migration module" - full_name = self.full_name() - try: - migration = sys.modules[full_name] - except KeyError: - try: - migration = __import__(full_name, {}, {}, ['Migration']) - except ImportError as e: - raise exceptions.UnknownMigration(self, sys.exc_info()) - except Exception as e: - raise exceptions.BrokenMigration(self, sys.exc_info()) - # Override some imports - migration._ = lambda x: x # Fake i18n - migration.datetime = datetime_utils - return migration - migration = memoize(migration) - - def migration_class(self): - "Returns the Migration class from the module" - return self.migration().Migration - - def migration_instance(self): - "Instantiates the migration_class" - return self.migration_class()() - migration_instance = memoize(migration_instance) - - def previous(self): - "Returns the migration that comes before this one in the sequence." - index = self.migrations.index(self) - 1 - if index < 0: - return None - return self.migrations[index] - previous = memoize(previous) - - def next(self): - "Returns the migration that comes after this one in the sequence." - index = self.migrations.index(self) + 1 - if index >= len(self.migrations): - return None - return self.migrations[index] - next = memoize(next) - - def _get_dependency_objects(self, attrname): - """ - Given the name of an attribute (depends_on or needed_by), either yields - a list of migration objects representing it, or errors out. - """ - for app, name in getattr(self.migration_class(), attrname, []): - try: - migrations = Migrations(app) - except ImproperlyConfigured: - raise exceptions.DependsOnUnmigratedApplication(self, app) - migration = migrations.migration(name) - try: - migration.migration() - except exceptions.UnknownMigration: - raise exceptions.DependsOnUnknownMigration(self, migration) - if migration.is_before(self) == False: - raise exceptions.DependsOnHigherMigration(self, migration) - yield migration - - def calculate_dependencies(self): - """ - Loads dependency info for this migration, and stores it in itself - and any other relevant migrations. - """ - # Normal deps first - for migration in self._get_dependency_objects("depends_on"): - self.dependencies.add(migration) - migration.dependents.add(self) - # And reverse deps - for migration in self._get_dependency_objects("needed_by"): - self.dependents.add(migration) - migration.dependencies.add(self) - # And implicit ordering deps - previous = self.previous() - if previous: - self.dependencies.add(previous) - previous.dependents.add(self) - - def invalidate_module(self): - """ - Removes the cached version of this migration's module import, so we - have to re-import it. Used when south.db.db changes. - """ - reload(self.migration()) - self.migration._invalidate() - - def forwards(self): - return self.migration_instance().forwards - - def backwards(self): - return self.migration_instance().backwards - - def forwards_plan(self): - """ - Returns a list of Migration objects to be applied, in order. - - This list includes `self`, which will be applied last. - """ - return depends(self, lambda x: x.dependencies) - - def _backwards_plan(self): - return depends(self, lambda x: x.dependents) - - def backwards_plan(self): - """ - Returns a list of Migration objects to be unapplied, in order. - - This list includes `self`, which will be unapplied last. - """ - return list(self._backwards_plan()) - - def is_before(self, other): - if self.migrations == other.migrations: - if self.filename < other.filename: - return True - return False - - def is_after(self, other): - if self.migrations == other.migrations: - if self.filename > other.filename: - return True - return False - - def prev_orm(self): - if getattr(self.migration_class(), 'symmetrical', False): - return self.orm() - previous = self.previous() - if previous is None: - # First migration? The 'previous ORM' is empty. - return FakeORM(None, self.app_label()) - return previous.orm() - prev_orm = memoize(prev_orm) - - def orm(self): - return FakeORM(self.migration_class(), self.app_label()) - orm = memoize(orm) - - def no_dry_run(self): - migration_class = self.migration_class() - try: - return migration_class.no_dry_run - except AttributeError: - return False diff --git a/lib/python2.7/site-packages/south/migration/migrators.py b/lib/python2.7/site-packages/south/migration/migrators.py deleted file mode 100644 index f405a15..0000000 --- a/lib/python2.7/site-packages/south/migration/migrators.py +++ /dev/null @@ -1,379 +0,0 @@ -from __future__ import print_function - -from copy import copy, deepcopy -import datetime -import inspect -import sys -import traceback - -from django.core.management import call_command -from django.core.management.commands import loaddata -from django.db import models -from django import VERSION as DJANGO_VERSION - -import south.db -from south import exceptions -from south.db import DEFAULT_DB_ALIAS -from south.models import MigrationHistory -from south.signals import ran_migration -from south.utils.py3 import StringIO - - -class Migrator(object): - def __init__(self, verbosity=0, interactive=False): - self.verbosity = int(verbosity) - self.interactive = bool(interactive) - - @staticmethod - def title(target): - raise NotImplementedError() - - def print_title(self, target): - if self.verbosity: - print(self.title(target)) - - @staticmethod - def status(target): - raise NotImplementedError() - - def print_status(self, migration): - status = self.status(migration) - if self.verbosity and status: - print(status) - - @staticmethod - def orm(migration): - raise NotImplementedError() - - def backwards(self, migration): - return self._wrap_direction(migration.backwards(), migration.prev_orm()) - - def direction(self, migration): - raise NotImplementedError() - - @staticmethod - def _wrap_direction(direction, orm): - args = inspect.getargspec(direction) - if len(args[0]) == 1: - # Old migration, no ORM should be passed in - return direction - return (lambda: direction(orm)) - - @staticmethod - def record(migration, database): - raise NotImplementedError() - - def run_migration_error(self, migration, extra_info=''): - return ( - ' ! Error found during real run of migration! Aborting.\n' - '\n' - ' ! Since you have a database that does not support running\n' - ' ! schema-altering statements in transactions, we have had \n' - ' ! to leave it in an interim state between migrations.\n' - '%s\n' - ' ! The South developers regret this has happened, and would\n' - ' ! like to gently persuade you to consider a slightly\n' - ' ! easier-to-deal-with DBMS (one that supports DDL transactions)\n' - ' ! NOTE: The error which caused the migration to fail is further up.' - ) % extra_info - - def run_migration(self, migration, database): - migration_function = self.direction(migration) - south.db.db.start_transaction() - try: - migration_function() - south.db.db.execute_deferred_sql() - if not isinstance(getattr(self, '_wrapper', self), DryRunMigrator): - # record us as having done this in the same transaction, - # since we're not in a dry run - self.record(migration, database) - except: - south.db.db.rollback_transaction() - if not south.db.db.has_ddl_transactions: - print(self.run_migration_error(migration)) - print("Error in migration: %s" % migration) - raise - else: - try: - south.db.db.commit_transaction() - except: - print("Error during commit in migration: %s" % migration) - raise - - - def run(self, migration, database): - # Get the correct ORM. - south.db.db.current_orm = self.orm(migration) - # If we're not already in a dry run, and the database doesn't support - # running DDL inside a transaction, *cough*MySQL*cough* then do a dry - # run first. - if not isinstance(getattr(self, '_wrapper', self), DryRunMigrator): - if not south.db.db.has_ddl_transactions: - dry_run = DryRunMigrator(migrator=self, ignore_fail=False) - dry_run.run_migration(migration, database) - return self.run_migration(migration, database) - - - def send_ran_migration(self, migration, database): - ran_migration.send(None, - app=migration.app_label(), - migration=migration, - method=self.__class__.__name__.lower(), - verbosity=self.verbosity, - interactive=self.interactive, - db=database) - - def migrate(self, migration, database): - """ - Runs the specified migration forwards/backwards, in order. - """ - app = migration.migrations._migrations - migration_name = migration.name() - self.print_status(migration) - result = self.run(migration, database) - self.send_ran_migration(migration, database) - return result - - def migrate_many(self, target, migrations, database): - raise NotImplementedError() - - -class MigratorWrapper(object): - def __init__(self, migrator, *args, **kwargs): - self._migrator = copy(migrator) - attributes = dict([(k, getattr(self, k)) - for k in self.__class__.__dict__ - if not k.startswith('__')]) - self._migrator.__dict__.update(attributes) - self._migrator.__dict__['_wrapper'] = self - - def __getattr__(self, name): - return getattr(self._migrator, name) - - -class DryRunMigrator(MigratorWrapper): - def __init__(self, ignore_fail=True, *args, **kwargs): - super(DryRunMigrator, self).__init__(*args, **kwargs) - self._ignore_fail = ignore_fail - - def _run_migration(self, migration): - if migration.no_dry_run(): - if self.verbosity: - print(" - Migration '%s' is marked for no-dry-run." % migration) - return - south.db.db.dry_run = True - # preserve the constraint cache as it can be mutated by the dry run - constraint_cache = deepcopy(south.db.db._constraint_cache) - if self._ignore_fail: - south.db.db.debug, old_debug = False, south.db.db.debug - pending_creates = south.db.db.get_pending_creates() - south.db.db.start_transaction() - migration_function = self.direction(migration) - try: - try: - migration_function() - south.db.db.execute_deferred_sql() - except: - raise exceptions.FailedDryRun(migration, sys.exc_info()) - finally: - south.db.db.rollback_transactions_dry_run() - if self._ignore_fail: - south.db.db.debug = old_debug - south.db.db.clear_run_data(pending_creates) - south.db.db.dry_run = False - # restore the preserved constraint cache from before dry run was - # executed - south.db.db._constraint_cache = constraint_cache - - def run_migration(self, migration, database): - try: - self._run_migration(migration) - except exceptions.FailedDryRun: - if self._ignore_fail: - return False - raise - - def send_ran_migration(self, *args, **kwargs): - pass - - -class FakeMigrator(MigratorWrapper): - def run(self, migration, database): - # Don't actually run, just record as if ran - self.record(migration, database) - if self.verbosity: - print(' (faked)') - - def send_ran_migration(self, *args, **kwargs): - pass - - -class LoadInitialDataMigrator(MigratorWrapper): - - def load_initial_data(self, target, db='default'): - if target is None or target != target.migrations[-1]: - return - # Load initial data, if we ended up at target - if self.verbosity: - print(" - Loading initial data for %s." % target.app_label()) - if DJANGO_VERSION < (1, 6): - self.pre_1_6(target, db) - else: - self.post_1_6(target, db) - - def pre_1_6(self, target, db): - # Override Django's get_apps call temporarily to only load from the - # current app - old_get_apps = models.get_apps - new_get_apps = lambda: [models.get_app(target.app_label())] - models.get_apps = new_get_apps - loaddata.get_apps = new_get_apps - try: - call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=db) - finally: - models.get_apps = old_get_apps - loaddata.get_apps = old_get_apps - - def post_1_6(self, target, db): - import django.db.models.loading - ## build a new 'AppCache' object with just the app we care about. - old_cache = django.db.models.loading.cache - new_cache = django.db.models.loading.AppCache() - new_cache.get_apps = lambda: [new_cache.get_app(target.app_label())] - - ## monkeypatch - django.db.models.loading.cache = new_cache - try: - call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=db) - finally: - ## unmonkeypatch - django.db.models.loading.cache = old_cache - - def migrate_many(self, target, migrations, database): - migrator = self._migrator - result = migrator.__class__.migrate_many(migrator, target, migrations, database) - if result: - self.load_initial_data(target, db=database) - return True - - -class Forwards(Migrator): - """ - Runs the specified migration forwards, in order. - """ - torun = 'forwards' - - @staticmethod - def title(target): - if target is not None: - return " - Migrating forwards to %s." % target.name() - else: - assert False, "You cannot migrate forwards to zero." - - @staticmethod - def status(migration): - return ' > %s' % migration - - @staticmethod - def orm(migration): - return migration.orm() - - def forwards(self, migration): - return self._wrap_direction(migration.forwards(), migration.orm()) - - direction = forwards - - @staticmethod - def record(migration, database): - # Record us as having done this - record = MigrationHistory.for_migration(migration, database) - try: - from django.utils.timezone import now - record.applied = now() - except ImportError: - record.applied = datetime.datetime.utcnow() - if database != DEFAULT_DB_ALIAS: - record.save(using=database) - else: - # Django 1.1 and below always go down this branch. - record.save() - - def format_backwards(self, migration): - if migration.no_dry_run(): - return " (migration cannot be dry-run; cannot discover commands)" - old_debug, old_dry_run = south.db.db.debug, south.db.db.dry_run - south.db.db.debug = south.db.db.dry_run = True - stdout = sys.stdout - sys.stdout = StringIO() - try: - try: - self.backwards(migration)() - return sys.stdout.getvalue() - except: - raise - finally: - south.db.db.debug, south.db.db.dry_run = old_debug, old_dry_run - sys.stdout = stdout - - def run_migration_error(self, migration, extra_info=''): - extra_info = ('\n' - '! You *might* be able to recover with:' - '%s' - '%s' % - (self.format_backwards(migration), extra_info)) - return super(Forwards, self).run_migration_error(migration, extra_info) - - def migrate_many(self, target, migrations, database): - try: - for migration in migrations: - result = self.migrate(migration, database) - if result is False: # The migrations errored, but nicely. - return False - finally: - # Call any pending post_syncdb signals - south.db.db.send_pending_create_signals(verbosity=self.verbosity, - interactive=self.interactive) - return True - - -class Backwards(Migrator): - """ - Runs the specified migration backwards, in order. - """ - torun = 'backwards' - - @staticmethod - def title(target): - if target is None: - return " - Migrating backwards to zero state." - else: - return " - Migrating backwards to just after %s." % target.name() - - @staticmethod - def status(migration): - return ' < %s' % migration - - @staticmethod - def orm(migration): - return migration.prev_orm() - - direction = Migrator.backwards - - @staticmethod - def record(migration, database): - # Record us as having not done this - record = MigrationHistory.for_migration(migration, database) - if record.id is not None: - if database != DEFAULT_DB_ALIAS: - record.delete(using=database) - else: - # Django 1.1 always goes down here - record.delete() - - def migrate_many(self, target, migrations, database): - for migration in migrations: - self.migrate(migration, database) - return True - - - diff --git a/lib/python2.7/site-packages/south/migration/utils.py b/lib/python2.7/site-packages/south/migration/utils.py deleted file mode 100644 index 68b9164..0000000 --- a/lib/python2.7/site-packages/south/migration/utils.py +++ /dev/null @@ -1,94 +0,0 @@ -import sys -from collections import deque - -from django.utils.datastructures import SortedDict -from django.db import models - -from south import exceptions - - -class SortedSet(SortedDict): - def __init__(self, data=tuple()): - self.extend(data) - - def __str__(self): - return "SortedSet(%s)" % list(self) - - def add(self, value): - self[value] = True - - def remove(self, value): - del self[value] - - def extend(self, iterable): - [self.add(k) for k in iterable] - - -def get_app_label(app): - """ - Returns the _internal_ app label for the given app module. - i.e. for <module django.contrib.auth.models> will return 'auth' - """ - return app.__name__.split('.')[-2] - - -def app_label_to_app_module(app_label): - """ - Given the app label, returns the module of the app itself (unlike models.get_app, - which returns the models module) - """ - # Get the models module - app = models.get_app(app_label) - module_name = ".".join(app.__name__.split(".")[:-1]) - try: - module = sys.modules[module_name] - except KeyError: - __import__(module_name, {}, {}, ['']) - module = sys.modules[module_name] - return module - - -def flatten(*stack): - stack = deque(stack) - while stack: - try: - x = next(stack[0]) - except TypeError: - stack[0] = iter(stack[0]) - x = next(stack[0]) - except StopIteration: - stack.popleft() - continue - if hasattr(x, '__iter__') and not isinstance(x, str): - stack.appendleft(x) - else: - yield x - -dependency_cache = {} - -def _dfs(start, get_children, path): - if (start, get_children) in dependency_cache: - return dependency_cache[(start, get_children)] - - results = [] - if start in path: - raise exceptions.CircularDependency(path[path.index(start):] + [start]) - path.append(start) - results.append(start) - children = sorted(get_children(start), key=lambda x: str(x)) - - # We need to apply all the migrations this one depends on - for n in children: - results = _dfs(n, get_children, path) + results - - path.pop() - - results = list(SortedSet(results)) - dependency_cache[(start, get_children)] = results - return results - -def dfs(start, get_children): - return _dfs(start, get_children, []) - -def depends(start, get_children): - return dfs(start, get_children) diff --git a/lib/python2.7/site-packages/south/models.py b/lib/python2.7/site-packages/south/models.py deleted file mode 100644 index 8239d61..0000000 --- a/lib/python2.7/site-packages/south/models.py +++ /dev/null @@ -1,37 +0,0 @@ -from django.db import models -from south.db import DEFAULT_DB_ALIAS - -class MigrationHistory(models.Model): - app_name = models.CharField(max_length=255) - migration = models.CharField(max_length=255) - applied = models.DateTimeField(blank=True) - - @classmethod - def for_migration(cls, migration, database): - try: - # Switch on multi-db-ness - if database != DEFAULT_DB_ALIAS: - # Django 1.2 - objects = cls.objects.using(database) - else: - # Django <= 1.1 - objects = cls.objects - return objects.get( - app_name=migration.app_label(), - migration=migration.name(), - ) - except cls.DoesNotExist: - return cls( - app_name=migration.app_label(), - migration=migration.name(), - ) - - def get_migrations(self): - from south.migration.base import Migrations - return Migrations(self.app_name) - - def get_migration(self): - return self.get_migrations().migration(self.migration) - - def __str__(self): - return "<%s: %s>" % (self.app_name, self.migration) diff --git a/lib/python2.7/site-packages/south/modelsinspector.py b/lib/python2.7/site-packages/south/modelsinspector.py deleted file mode 100644 index 13e493d..0000000 --- a/lib/python2.7/site-packages/south/modelsinspector.py +++ /dev/null @@ -1,464 +0,0 @@ -""" -Like the old south.modelsparser, but using introspection where possible -rather than direct inspection of models.py. -""" - -from __future__ import print_function - -import datetime -import re -import decimal - -from south.utils import get_attribute, auto_through -from south.utils.py3 import text_type - -from django.db import models -from django.db.models.base import ModelBase, Model -from django.db.models.fields import NOT_PROVIDED -from django.conf import settings -from django.utils.functional import Promise -from django.contrib.contenttypes import generic -from django.utils.datastructures import SortedDict -from django.utils import datetime_safe - -NOISY = False - -try: - from django.utils import timezone -except ImportError: - timezone = False - - -# Define any converter functions first to prevent NameErrors - -def convert_on_delete_handler(value): - django_db_models_module = 'models' # relative to standard import 'django.db' - if hasattr(models, "PROTECT"): - if value in (models.CASCADE, models.PROTECT, models.DO_NOTHING, models.SET_DEFAULT): - # straightforward functions - return '%s.%s' % (django_db_models_module, value.__name__) - else: - # This is totally dependent on the implementation of django.db.models.deletion.SET - func_name = getattr(value, '__name__', None) - if func_name == 'set_on_delete': - # we must inspect the function closure to see what parameters were passed in - closure_contents = value.__closure__[0].cell_contents - if closure_contents is None: - return "%s.SET_NULL" % (django_db_models_module) - # simple function we can perhaps cope with: - elif hasattr(closure_contents, '__call__'): - raise ValueError("South does not support on_delete with SET(function) as values.") - else: - # Attempt to serialise the value - return "%s.SET(%s)" % (django_db_models_module, value_clean(closure_contents)) - raise ValueError("%s was not recognized as a valid model deletion handler. Possible values: %s." % (value, ', '.join(f.__name__ for f in (models.CASCADE, models.PROTECT, models.SET, models.SET_NULL, models.SET_DEFAULT, models.DO_NOTHING)))) - else: - raise ValueError("on_delete argument encountered in Django version that does not support it") - -# Gives information about how to introspect certain fields. -# This is a list of triples; the first item is a list of fields it applies to, -# (note that isinstance is used, so superclasses are perfectly valid here) -# the second is a list of positional argument descriptors, and the third -# is a list of keyword argument descriptors. -# Descriptors are of the form: -# [attrname, options] -# Where attrname is the attribute on the field to get the value from, and options -# is an optional dict. -# -# The introspector uses the combination of all matching entries, in order. - -introspection_details = [ - ( - (models.Field, ), - [], - { - "null": ["null", {"default": False}], - "blank": ["blank", {"default": False, "ignore_if":"primary_key"}], - "primary_key": ["primary_key", {"default": False}], - "max_length": ["max_length", {"default": None}], - "unique": ["_unique", {"default": False}], - "db_index": ["db_index", {"default": False}], - "default": ["default", {"default": NOT_PROVIDED, "ignore_dynamics": True}], - "db_column": ["db_column", {"default": None}], - "db_tablespace": ["db_tablespace", {"default": settings.DEFAULT_INDEX_TABLESPACE}], - }, - ), - ( - (models.ForeignKey, models.OneToOneField), - [], - dict([ - ("to", ["rel.to", {}]), - ("to_field", ["rel.field_name", {"default_attr": "rel.to._meta.pk.name"}]), - ("related_name", ["rel.related_name", {"default": None}]), - ("db_index", ["db_index", {"default": True}]), - ("on_delete", ["rel.on_delete", {"default": getattr(models, "CASCADE", None), "is_django_function": True, "converter": convert_on_delete_handler, "ignore_missing": True}]) - ]) - ), - ( - (models.ManyToManyField,), - [], - { - "to": ["rel.to", {}], - "symmetrical": ["rel.symmetrical", {"default": True}], - "related_name": ["rel.related_name", {"default": None}], - "db_table": ["db_table", {"default": None}], - # TODO: Kind of ugly to add this one-time-only option - "through": ["rel.through", {"ignore_if_auto_through": True}], - }, - ), - ( - (models.DateField, models.TimeField), - [], - { - "auto_now": ["auto_now", {"default": False}], - "auto_now_add": ["auto_now_add", {"default": False}], - }, - ), - ( - (models.DecimalField, ), - [], - { - "max_digits": ["max_digits", {"default": None}], - "decimal_places": ["decimal_places", {"default": None}], - }, - ), - ( - (models.SlugField, ), - [], - { - "db_index": ["db_index", {"default": True}], - }, - ), - ( - (models.BooleanField, ), - [], - { - "default": ["default", {"default": NOT_PROVIDED, "converter": bool}], - "blank": ["blank", {"default": True, "ignore_if":"primary_key"}], - }, - ), - ( - (models.FilePathField, ), - [], - { - "path": ["path", {"default": ''}], - "match": ["match", {"default": None}], - "recursive": ["recursive", {"default": False}], - }, - ), - ( - (generic.GenericRelation, ), - [], - { - "to": ["rel.to", {}], - "symmetrical": ["rel.symmetrical", {"default": True}], - "object_id_field": ["object_id_field_name", {"default": "object_id"}], - "content_type_field": ["content_type_field_name", {"default": "content_type"}], - "blank": ["blank", {"default": True}], - }, - ), -] - -# Regexes of allowed field full paths -allowed_fields = [ - "^django\.db", - "^django\.contrib\.contenttypes\.generic", - "^django\.contrib\.localflavor", - "^django_localflavor_\w\w", -] - -# Regexes of ignored fields (custom fields which look like fields, but have no column behind them) -ignored_fields = [ - "^django\.contrib\.contenttypes\.generic\.GenericRelation", - "^django\.contrib\.contenttypes\.generic\.GenericForeignKey", -] - -# Similar, but for Meta, so just the inner level (kwds). -meta_details = { - "db_table": ["db_table", {"default_attr_concat": ["%s_%s", "app_label", "module_name"]}], - "db_tablespace": ["db_tablespace", {"default": settings.DEFAULT_TABLESPACE}], - "unique_together": ["unique_together", {"default": []}], - "index_together": ["index_together", {"default": [], "ignore_missing": True}], - "ordering": ["ordering", {"default": []}], - "proxy": ["proxy", {"default": False, "ignore_missing": True}], -} - - -def add_introspection_rules(rules=[], patterns=[]): - "Allows you to add some introspection rules at runtime, e.g. for 3rd party apps." - assert isinstance(rules, (list, tuple)) - assert isinstance(patterns, (list, tuple)) - allowed_fields.extend(patterns) - introspection_details.extend(rules) - - -def add_ignored_fields(patterns): - "Allows you to add some ignore field patterns." - assert isinstance(patterns, (list, tuple)) - ignored_fields.extend(patterns) - - -def can_ignore(field): - """ - Returns True if we know for certain that we can ignore this field, False - otherwise. - """ - full_name = "%s.%s" % (field.__class__.__module__, field.__class__.__name__) - for regex in ignored_fields: - if re.match(regex, full_name): - return True - return False - - -def can_introspect(field): - """ - Returns True if we are allowed to introspect this field, False otherwise. - ('allowed' means 'in core'. Custom fields can declare they are introspectable - by the default South rules by adding the attribute _south_introspects = True.) - """ - # Check for special attribute - if hasattr(field, "_south_introspects") and field._south_introspects: - return True - # Check it's an introspectable field - full_name = "%s.%s" % (field.__class__.__module__, field.__class__.__name__) - for regex in allowed_fields: - if re.match(regex, full_name): - return True - return False - - -def matching_details(field): - """ - Returns the union of all matching entries in introspection_details for the field. - """ - our_args = [] - our_kwargs = {} - for classes, args, kwargs in introspection_details: - if any([isinstance(field, x) for x in classes]): - our_args.extend(args) - our_kwargs.update(kwargs) - return our_args, our_kwargs - - -class IsDefault(Exception): - """ - Exception for when a field contains its default value. - """ - - -def get_value(field, descriptor): - """ - Gets an attribute value from a Field instance and formats it. - """ - attrname, options = descriptor - # If the options say it's not a attribute name but a real value, use that. - if options.get('is_value', False): - value = attrname - else: - try: - value = get_attribute(field, attrname) - except AttributeError: - if options.get("ignore_missing", False): - raise IsDefault - else: - raise - - # Lazy-eval functions get eval'd. - if isinstance(value, Promise): - value = text_type(value) - # If the value is the same as the default, omit it for clarity - if "default" in options and value == options['default']: - raise IsDefault - # If there's an ignore_if, use it - if "ignore_if" in options: - if get_attribute(field, options['ignore_if']): - raise IsDefault - # If there's an ignore_if_auto_through which is True, use it - if options.get("ignore_if_auto_through", False): - if auto_through(field): - raise IsDefault - # Some default values need to be gotten from an attribute too. - if "default_attr" in options: - default_value = get_attribute(field, options['default_attr']) - if value == default_value: - raise IsDefault - # Some are made from a formatting string and several attrs (e.g. db_table) - if "default_attr_concat" in options: - format, attrs = options['default_attr_concat'][0], options['default_attr_concat'][1:] - default_value = format % tuple(map(lambda x: get_attribute(field, x), attrs)) - if value == default_value: - raise IsDefault - # Clean and return the value - return value_clean(value, options) - - -def value_clean(value, options={}): - "Takes a value and cleans it up (so e.g. it has timezone working right)" - # Lazy-eval functions get eval'd. - if isinstance(value, Promise): - value = text_type(value) - # Callables get called. - if not options.get('is_django_function', False) and callable(value) and not isinstance(value, ModelBase): - # Datetime.datetime.now is special, as we can access it from the eval - # context (and because it changes all the time; people will file bugs otherwise). - if value == datetime.datetime.now: - return "datetime.datetime.now" - elif value == datetime.datetime.utcnow: - return "datetime.datetime.utcnow" - elif value == datetime.date.today: - return "datetime.date.today" - # In case we use Django's own now function, revert to datetime's - # original one since we'll deal with timezones on our own. - elif timezone and value == timezone.now: - return "datetime.datetime.now" - # All other callables get called. - value = value() - # Models get their own special repr() - if isinstance(value, ModelBase): - # If it's a proxy model, follow it back to its non-proxy parent - if getattr(value._meta, "proxy", False): - value = value._meta.proxy_for_model - return "orm['%s.%s']" % (value._meta.app_label, value._meta.object_name) - # As do model instances - if isinstance(value, Model): - if options.get("ignore_dynamics", False): - raise IsDefault - return "orm['%s.%s'].objects.get(pk=%r)" % (value.__class__._meta.app_label, value.__class__._meta.object_name, value.pk) - # Make sure Decimal is converted down into a string - if isinstance(value, decimal.Decimal): - value = str(value) - # in case the value is timezone aware - datetime_types = ( - datetime.datetime, - datetime.time, - datetime_safe.datetime, - ) - if (timezone and isinstance(value, datetime_types) and - getattr(settings, 'USE_TZ', False) and - value is not None and timezone.is_aware(value)): - default_timezone = timezone.get_default_timezone() - value = timezone.make_naive(value, default_timezone) - # datetime_safe has an improper repr value - if isinstance(value, datetime_safe.datetime): - value = datetime.datetime(*value.utctimetuple()[:7]) - # converting a date value to a datetime to be able to handle - # timezones later gracefully - elif isinstance(value, (datetime.date, datetime_safe.date)): - value = datetime.datetime(*value.timetuple()[:3]) - # Now, apply the converter func if there is one - if "converter" in options: - value = options['converter'](value) - # Return the final value - if options.get('is_django_function', False): - return value - else: - return repr(value) - - -def introspector(field): - """ - Given a field, introspects its definition triple. - """ - arg_defs, kwarg_defs = matching_details(field) - args = [] - kwargs = {} - # For each argument, use the descriptor to get the real value. - for defn in arg_defs: - try: - args.append(get_value(field, defn)) - except IsDefault: - pass - for kwd, defn in kwarg_defs.items(): - try: - kwargs[kwd] = get_value(field, defn) - except IsDefault: - pass - return args, kwargs - - -def get_model_fields(model, m2m=False): - """ - Given a model class, returns a dict of {field_name: field_triple} defs. - """ - - field_defs = SortedDict() - inherited_fields = {} - - # Go through all bases (that are themselves models, but not Model) - for base in model.__bases__: - if hasattr(base, '_meta') and issubclass(base, models.Model): - if not base._meta.abstract: - # Looks like we need their fields, Ma. - inherited_fields.update(get_model_fields(base)) - - # Now, go through all the fields and try to get their definition - source = model._meta.local_fields[:] - if m2m: - source += model._meta.local_many_to_many - - for field in source: - # Can we ignore it completely? - if can_ignore(field): - continue - # Does it define a south_field_triple method? - if hasattr(field, "south_field_triple"): - if NOISY: - print(" ( Nativing field: %s" % field.name) - field_defs[field.name] = field.south_field_triple() - # Can we introspect it? - elif can_introspect(field): - # Get the full field class path. - field_class = field.__class__.__module__ + "." + field.__class__.__name__ - # Run this field through the introspector - args, kwargs = introspector(field) - # Workaround for Django bug #13987 - if model._meta.pk.column == field.column and 'primary_key' not in kwargs: - kwargs['primary_key'] = True - # That's our definition! - field_defs[field.name] = (field_class, args, kwargs) - # Shucks, no definition! - else: - if NOISY: - print(" ( Nodefing field: %s" % field.name) - field_defs[field.name] = None - - # If they've used the horrific hack that is order_with_respect_to, deal with - # it. - if model._meta.order_with_respect_to: - field_defs['_order'] = ("django.db.models.fields.IntegerField", [], {"default": "0"}) - - return field_defs - - -def get_model_meta(model): - """ - Given a model class, will return the dict representing the Meta class. - """ - - # Get the introspected attributes - meta_def = {} - for kwd, defn in meta_details.items(): - try: - meta_def[kwd] = get_value(model._meta, defn) - except IsDefault: - pass - - # Also, add on any non-abstract model base classes. - # This is called _ormbases as the _bases variable was previously used - # for a list of full class paths to bases, so we can't conflict. - for base in model.__bases__: - if hasattr(base, '_meta') and issubclass(base, models.Model): - if not base._meta.abstract: - # OK, that matches our terms. - if "_ormbases" not in meta_def: - meta_def['_ormbases'] = [] - meta_def['_ormbases'].append("%s.%s" % ( - base._meta.app_label, - base._meta.object_name, - )) - - return meta_def - - -# Now, load the built-in South introspection plugins -import south.introspection_plugins diff --git a/lib/python2.7/site-packages/south/orm.py b/lib/python2.7/site-packages/south/orm.py deleted file mode 100644 index 8d46ee7..0000000 --- a/lib/python2.7/site-packages/south/orm.py +++ /dev/null @@ -1,407 +0,0 @@ -""" -South's fake ORM; lets you not have to write SQL inside migrations. -Roughly emulates the real Django ORM, to a point. -""" - -from __future__ import print_function - -import inspect - -from django.db import models -from django.db.models.loading import cache -from django.core.exceptions import ImproperlyConfigured - -from south.db import db -from south.utils import ask_for_it_by_name, datetime_utils -from south.hacks import hacks -from south.exceptions import UnfreezeMeLater, ORMBaseNotIncluded, ImpossibleORMUnfreeze -from south.utils.py3 import string_types - - -class ModelsLocals(object): - - """ - Custom dictionary-like class to be locals(); - falls back to lowercase search for items that don't exist - (because we store model names as lowercase). - """ - - def __init__(self, data): - self.data = data - - def __getitem__(self, key): - try: - return self.data[key] - except KeyError: - return self.data[key.lower()] - - -# Stores already-created ORMs. -_orm_cache = {} - -def FakeORM(*args): - """ - Creates a Fake Django ORM. - This is actually a memoised constructor; the real class is _FakeORM. - """ - if not args in _orm_cache: - _orm_cache[args] = _FakeORM(*args) - return _orm_cache[args] - - -class LazyFakeORM(object): - """ - In addition to memoising the ORM call, this function lazily generates them - for a Migration class. Assign the result of this to (for example) - .orm, and as soon as .orm is accessed the ORM will be created. - """ - - def __init__(self, *args): - self._args = args - self.orm = None - - def __get__(self, obj, type=None): - if not self.orm: - self.orm = FakeORM(*self._args) - return self.orm - - -class _FakeORM(object): - - """ - Simulates the Django ORM at some point in time, - using a frozen definition on the Migration class. - """ - - def __init__(self, cls, app): - self.default_app = app - self.cls = cls - # Try loading the models off the migration class; default to no models. - self.models = {} - try: - self.models_source = cls.models - except AttributeError: - return - - # Start a 'new' AppCache - hacks.clear_app_cache() - - # Now, make each model's data into a FakeModel - # We first make entries for each model that are just its name - # This allows us to have circular model dependency loops - model_names = [] - for name, data in self.models_source.items(): - # Make sure there's some kind of Meta - if "Meta" not in data: - data['Meta'] = {} - try: - app_label, model_name = name.split(".", 1) - except ValueError: - app_label = self.default_app - model_name = name - - # If there's an object_name in the Meta, use it and remove it - if "object_name" in data['Meta']: - model_name = data['Meta']['object_name'] - del data['Meta']['object_name'] - - name = "%s.%s" % (app_label, model_name) - self.models[name.lower()] = name - model_names.append((name.lower(), app_label, model_name, data)) - - # Loop until model_names is entry, or hasn't shrunk in size since - # last iteration. - # The make_model method can ask to postpone a model; it's then pushed - # to the back of the queue. Because this is currently only used for - # inheritance, it should thus theoretically always decrease by one. - last_size = None - while model_names: - # First, make sure we've shrunk. - if len(model_names) == last_size: - raise ImpossibleORMUnfreeze() - last_size = len(model_names) - # Make one run through - postponed_model_names = [] - for name, app_label, model_name, data in model_names: - try: - self.models[name] = self.make_model(app_label, model_name, data) - except UnfreezeMeLater: - postponed_model_names.append((name, app_label, model_name, data)) - # Reset - model_names = postponed_model_names - - # And perform the second run to iron out any circular/backwards depends. - self.retry_failed_fields() - - # Force evaluation of relations on the models now - for model in self.models.values(): - model._meta.get_all_field_names() - - # Reset AppCache - hacks.unclear_app_cache() - - - def __iter__(self): - return iter(self.models.values()) - - - def __getattr__(self, key): - fullname = (self.default_app+"."+key).lower() - try: - return self.models[fullname] - except KeyError: - raise AttributeError("The model '%s' from the app '%s' is not available in this migration. (Did you use orm.ModelName, not orm['app.ModelName']?)" % (key, self.default_app)) - - - def __getitem__(self, key): - # Detect if they asked for a field on a model or not. - if ":" in key: - key, fname = key.split(":") - else: - fname = None - # Now, try getting the model - key = key.lower() - try: - model = self.models[key] - except KeyError: - try: - app, model = key.split(".", 1) - except ValueError: - raise KeyError("The model '%s' is not in appname.modelname format." % key) - else: - raise KeyError("The model '%s' from the app '%s' is not available in this migration." % (model, app)) - # If they asked for a field, get it. - if fname: - return model._meta.get_field_by_name(fname)[0] - else: - return model - - - def eval_in_context(self, code, app, extra_imports={}): - "Evaluates the given code in the context of the migration file." - - # Drag in the migration module's locals (hopefully including models.py) - # excluding all models from that (i.e. from modern models.py), to stop pollution - fake_locals = dict( - (key, value) - for key, value in inspect.getmodule(self.cls).__dict__.items() - if not ( - isinstance(value, type) - and issubclass(value, models.Model) - and hasattr(value, "_meta") - ) - ) - - # We add our models into the locals for the eval - fake_locals.update(dict([ - (name.split(".")[-1], model) - for name, model in self.models.items() - ])) - - # Make sure the ones for this app override. - fake_locals.update(dict([ - (name.split(".")[-1], model) - for name, model in self.models.items() - if name.split(".")[0] == app - ])) - - # Ourselves as orm, to allow non-fail cross-app referencing - fake_locals['orm'] = self - - # And a fake _ function - fake_locals['_'] = lambda x: x - - # Datetime; there should be no datetime direct accesses - fake_locals['datetime'] = datetime_utils - - # Now, go through the requested imports and import them. - for name, value in extra_imports.items(): - # First, try getting it out of locals. - parts = value.split(".") - try: - obj = fake_locals[parts[0]] - for part in parts[1:]: - obj = getattr(obj, part) - except (KeyError, AttributeError): - pass - else: - fake_locals[name] = obj - continue - # OK, try to import it directly - try: - fake_locals[name] = ask_for_it_by_name(value) - except ImportError: - if name == "SouthFieldClass": - raise ValueError("Cannot import the required field '%s'" % value) - else: - print("WARNING: Cannot import '%s'" % value) - - # Use ModelsLocals to make lookups work right for CapitalisedModels - fake_locals = ModelsLocals(fake_locals) - - return eval(code, globals(), fake_locals) - - - def make_meta(self, app, model, data, stub=False): - "Makes a Meta class out of a dict of eval-able arguments." - results = {'app_label': app} - for key, code in data.items(): - # Some things we never want to use. - if key in ["_bases", "_ormbases"]: - continue - # Some things we don't want with stubs. - if stub and key in ["order_with_respect_to"]: - continue - # OK, add it. - try: - results[key] = self.eval_in_context(code, app) - except (NameError, AttributeError) as e: - raise ValueError("Cannot successfully create meta field '%s' for model '%s.%s': %s." % ( - key, app, model, e - )) - return type("Meta", tuple(), results) - - - def make_model(self, app, name, data): - "Makes a Model class out of the given app name, model name and pickled data." - - # Extract any bases out of Meta - if "_ormbases" in data['Meta']: - # Make sure everything we depend on is done already; otherwise, wait. - for key in data['Meta']['_ormbases']: - key = key.lower() - if key not in self.models: - raise ORMBaseNotIncluded("Cannot find ORM base %s" % key) - elif isinstance(self.models[key], string_types): - # Then the other model hasn't been unfrozen yet. - # We postpone ourselves; the situation will eventually resolve. - raise UnfreezeMeLater() - bases = [self.models[key.lower()] for key in data['Meta']['_ormbases']] - # Perhaps the old style? - elif "_bases" in data['Meta']: - bases = map(ask_for_it_by_name, data['Meta']['_bases']) - # Ah, bog standard, then. - else: - bases = [models.Model] - - # Turn the Meta dict into a basic class - meta = self.make_meta(app, name, data['Meta'], data.get("_stub", False)) - - failed_fields = {} - fields = {} - stub = False - - # Now, make some fields! - for fname, params in data.items(): - # If it's the stub marker, ignore it. - if fname == "_stub": - stub = bool(params) - continue - elif fname == "Meta": - continue - elif not params: - raise ValueError("Field '%s' on model '%s.%s' has no definition." % (fname, app, name)) - elif isinstance(params, string_types): - # It's a premade definition string! Let's hope it works... - code = params - extra_imports = {} - else: - # If there's only one parameter (backwards compat), make it 3. - if len(params) == 1: - params = (params[0], [], {}) - # There should be 3 parameters. Code is a tuple of (code, what-to-import) - if len(params) == 3: - code = "SouthFieldClass(%s)" % ", ".join( - params[1] + - ["%s=%s" % (n, v) for n, v in params[2].items()] - ) - extra_imports = {"SouthFieldClass": params[0]} - else: - raise ValueError("Field '%s' on model '%s.%s' has a weird definition length (should be 1 or 3 items)." % (fname, app, name)) - - try: - # Execute it in a probably-correct context. - field = self.eval_in_context(code, app, extra_imports) - except (NameError, AttributeError, AssertionError, KeyError): - # It might rely on other models being around. Add it to the - # model for the second pass. - failed_fields[fname] = (code, extra_imports) - else: - fields[fname] = field - - # Find the app in the Django core, and get its module - more_kwds = {} - try: - app_module = models.get_app(app) - more_kwds['__module__'] = app_module.__name__ - except ImproperlyConfigured: - # The app this belonged to has vanished, but thankfully we can still - # make a mock model, so ignore the error. - more_kwds['__module__'] = '_south_mock' - - more_kwds['Meta'] = meta - - # Make our model - fields.update(more_kwds) - - model = type( - str(name), - tuple(bases), - fields, - ) - - # If this is a stub model, change Objects to a whiny class - if stub: - model.objects = WhinyManager() - # Also, make sure they can't instantiate it - model.__init__ = whiny_method - else: - model.objects = NoDryRunManager(model.objects) - - if failed_fields: - model._failed_fields = failed_fields - - return model - - def retry_failed_fields(self): - "Tries to re-evaluate the _failed_fields for each model." - for modelkey, model in self.models.items(): - app, modelname = modelkey.split(".", 1) - if hasattr(model, "_failed_fields"): - for fname, (code, extra_imports) in model._failed_fields.items(): - try: - field = self.eval_in_context(code, app, extra_imports) - except (NameError, AttributeError, AssertionError, KeyError) as e: - # It's failed again. Complain. - raise ValueError("Cannot successfully create field '%s' for model '%s': %s." % ( - fname, modelname, e - )) - else: - # Startup that field. - model.add_to_class(fname, field) - - -class WhinyManager(object): - "A fake manager that whines whenever you try to touch it. For stub models." - - def __getattr__(self, key): - raise AttributeError("You cannot use items from a stub model.") - - -class NoDryRunManager(object): - """ - A manager that always proxies through to the real manager, - unless a dry run is in progress. - """ - - def __init__(self, real): - self.real = real - - def __getattr__(self, name): - if db.dry_run: - raise AttributeError("You are in a dry run, and cannot access the ORM.\nWrap ORM sections in 'if not db.dry_run:', or if the whole migration is only a data migration, set no_dry_run = True on the Migration class.") - return getattr(self.real, name) - - -def whiny_method(*a, **kw): - raise ValueError("You cannot instantiate a stub model.") diff --git a/lib/python2.7/site-packages/south/signals.py b/lib/python2.7/site-packages/south/signals.py deleted file mode 100644 index 12a1362..0000000 --- a/lib/python2.7/site-packages/south/signals.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -South-specific signals -""" - -from django.dispatch import Signal -from django.conf import settings - -# Sent at the start of the migration of an app -pre_migrate = Signal(providing_args=["app", "verbosity", "interactive", "db"]) - -# Sent after each successful migration of an app -post_migrate = Signal(providing_args=["app", "verbosity", "interactive", "db"]) - -# Sent after each run of a particular migration in a direction -ran_migration = Signal(providing_args=["app", "migration", "method", "verbosity", "interactive", "db"]) - -# Compatibility code for django.contrib.auth -# Is causing strange errors, removing for now (we might need to fix up orm first) -#if 'django.contrib.auth' in settings.INSTALLED_APPS: - #def create_permissions_compat(app, **kwargs): - #from django.db.models import get_app - #from django.contrib.auth.management import create_permissions - #create_permissions(get_app(app), (), 0) - #post_migrate.connect(create_permissions_compat) diff --git a/lib/python2.7/site-packages/south/test_shim.py b/lib/python2.7/site-packages/south/test_shim.py deleted file mode 100644 index fdf39f3..0000000 --- a/lib/python2.7/site-packages/south/test_shim.py +++ /dev/null @@ -1,6 +0,0 @@ -""" -This file is needed as 1.6 only finds tests in files labelled test_*, -and ignores tests/__init__.py. -""" - -from south.tests import * diff --git a/lib/python2.7/site-packages/south/tests/__init__.py b/lib/python2.7/site-packages/south/tests/__init__.py deleted file mode 100644 index 26779e3..0000000 --- a/lib/python2.7/site-packages/south/tests/__init__.py +++ /dev/null @@ -1,109 +0,0 @@ -from __future__ import print_function - -#import unittest -import os -import sys -from functools import wraps -from django.conf import settings -from south.hacks import hacks - -# Make sure skipping tests is available. -try: - # easiest and best is unittest included in Django>=1.3 - from django.utils import unittest -except ImportError: - # earlier django... use unittest from stdlib - import unittest -# however, skipUnless was only added in Python 2.7; -# if not available, we need to do something else -try: - skipUnless = unittest.skipUnless #@UnusedVariable -except AttributeError: - def skipUnless(condition, message): - def decorator(testfunc): - @wraps(testfunc) - def wrapper(self): - if condition: - # Apply method - testfunc(self) - else: - # The skip exceptions are not available either... - print("Skipping", testfunc.__name__,"--", message) - return wrapper - return decorator - -# ditto for skipIf -try: - skipIf = unittest.skipIf #@UnusedVariable -except AttributeError: - def skipIf(condition, message): - def decorator(testfunc): - @wraps(testfunc) - def wrapper(self): - if condition: - print("Skipping", testfunc.__name__,"--", message) - else: - # Apply method - testfunc(self) - return wrapper - return decorator - -# Add the tests directory so fakeapp is on sys.path -test_root = os.path.dirname(__file__) -sys.path.append(test_root) - -# Note: the individual test files are imported below this. - -class Monkeypatcher(unittest.TestCase): - - """ - Base test class for tests that play with the INSTALLED_APPS setting at runtime. - """ - - def create_fake_app(self, name): - - class Fake: - pass - - fake = Fake() - fake.__name__ = name - try: - fake.migrations = __import__(name + ".migrations", {}, {}, ['migrations']) - except ImportError: - pass - return fake - - def setUp(self): - """ - Changes the Django environment so we can run tests against our test apps. - """ - if hasattr(self, 'installed_apps'): - hacks.store_app_cache_state() - hacks.set_installed_apps(self.installed_apps) - # Make sure dependencies are calculated for new apps - Migrations._dependencies_done = False - - def tearDown(self): - """ - Undoes what setUp did. - """ - if hasattr(self, 'installed_apps'): - hacks.reset_installed_apps() - hacks.restore_app_cache_state() - - -# Try importing all tests if asked for (then we can run 'em) -try: - skiptest = settings.SKIP_SOUTH_TESTS -except: - skiptest = True - -if not skiptest: - from south.tests.db import * - from south.tests.db_mysql import * - from south.tests.db_firebird import * - from south.tests.logic import * - from south.tests.autodetection import * - from south.tests.logger import * - from south.tests.inspector import * - from south.tests.freezer import * diff --git a/lib/python2.7/site-packages/south/tests/autodetection.py b/lib/python2.7/site-packages/south/tests/autodetection.py deleted file mode 100644 index c320d3a..0000000 --- a/lib/python2.7/site-packages/south/tests/autodetection.py +++ /dev/null @@ -1,360 +0,0 @@ -from south.tests import unittest - -from south.creator.changes import AutoChanges, InitialChanges -from south.migration.base import Migrations -from south.tests import Monkeypatcher -from south.creator import freezer -from south.orm import FakeORM -from south.v2 import SchemaMigration - -try: - from django.utils.six.moves import reload_module -except ImportError: - # Older django, no python3 support - reload_module = reload - -class TestComparison(unittest.TestCase): - - """ - Tests the comparison methods of startmigration. - """ - - def test_no_change(self): - "Test with a completely unchanged definition." - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['southdemo.Lizard']"}), - ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['southdemo.Lizard']"}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.related.ForeignKey', ['ohhai', 'there'], {'to': "somewhere", "from": "there"}), - ('django.db.models.fields.related.ForeignKey', ['ohhai', 'there'], {"from": "there", 'to': "somewhere"}), - ), - False, - ) - - - def test_pos_change(self): - "Test with a changed positional argument." - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['hi'], {'to': "foo"}), - ('django.db.models.fields.CharField', [], {'to': "foo"}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', [], {'to': "foo"}), - ('django.db.models.fields.CharField', ['bye'], {'to': "foo"}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}), - ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['pisdadad'], {'to': "foo"}), - ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['hi'], {}), - ('django.db.models.fields.CharField', [], {}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', [], {}), - ('django.db.models.fields.CharField', ['bye'], {}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['pi'], {}), - ('django.db.models.fields.CharField', ['pi'], {}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['pi'], {}), - ('django.db.models.fields.CharField', ['45fdfdf'], {}), - ), - True, - ) - - - def test_kwd_change(self): - "Test a changed keyword argument" - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}), - ('django.db.models.fields.CharField', ['pi'], {'to': "blue"}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', [], {'to': "foo"}), - ('django.db.models.fields.CharField', [], {'to': "blue"}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['b'], {'to': "foo"}), - ('django.db.models.fields.CharField', ['b'], {'to': "blue"}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', [], {'to': "foo"}), - ('django.db.models.fields.CharField', [], {}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['a'], {'to': "foo"}), - ('django.db.models.fields.CharField', ['a'], {}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', [], {}), - ('django.db.models.fields.CharField', [], {'to': "foo"}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('django.db.models.fields.CharField', ['a'], {}), - ('django.db.models.fields.CharField', ['a'], {'to': "foo"}), - ), - True, - ) - - - - def test_backcompat_nochange(self): - "Test that the backwards-compatable comparison is working" - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', [], {}), - ('django.db.models.fields.CharField', [], {}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', ['ack'], {}), - ('django.db.models.fields.CharField', ['ack'], {}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', [], {'to':'b'}), - ('django.db.models.fields.CharField', [], {'to':'b'}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', ['hah'], {'to':'you'}), - ('django.db.models.fields.CharField', ['hah'], {'to':'you'}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', ['hah'], {'to':'you'}), - ('django.db.models.fields.CharField', ['hah'], {'to':'heh'}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', ['hah'], {}), - ('django.db.models.fields.CharField', [], {'to':"orm['appname.hah']"}), - ), - False, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', ['hah'], {}), - ('django.db.models.fields.CharField', [], {'to':'hah'}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', ['hah'], {}), - ('django.db.models.fields.CharField', [], {'to':'rrr'}), - ), - True, - ) - - self.assertEqual( - AutoChanges.different_attributes( - ('models.CharField', ['hah'], {}), - ('django.db.models.fields.IntField', [], {'to':'hah'}), - ), - True, - ) - -class TestNonManagedIgnored(Monkeypatcher): - - installed_apps = ["non_managed"] - - full_defs = { - 'non_managed.legacy': { - 'Meta': {'object_name': 'Legacy', 'db_table': "'legacy_table'", 'managed': 'False'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), - 'size': ('django.db.models.fields.IntegerField', [], {}) - } - } - - def test_not_added_init(self): - - migrations = Migrations("non_managed") - changes = InitialChanges(migrations) - change_list = changes.get_changes() - if list(change_list): - self.fail("Initial migration creates table for non-managed model") - - def test_not_added_auto(self): - - empty_defs = { } - class EmptyMigration(SchemaMigration): - "Serves as fake previous migration" - - def forwards(self, orm): - pass - - def backwards(self, orm): - pass - - models = empty_defs - - complete_apps = ['non_managed'] - - migrations = Migrations("non_managed") - empty_orm = FakeORM(EmptyMigration, "non_managed") - changes = AutoChanges( - migrations = migrations, - old_defs = empty_defs, - old_orm = empty_orm, - new_defs = self.full_defs, - ) - change_list = changes.get_changes() - if list(change_list): - self.fail("Auto migration creates table for non-managed model") - - def test_not_deleted_auto(self): - - empty_defs = { } - old_defs = freezer.freeze_apps(["non_managed"]) - class InitialMigration(SchemaMigration): - "Serves as fake previous migration" - - def forwards(self, orm): - pass - - def backwards(self, orm): - pass - - models = self.full_defs - - complete_apps = ['non_managed'] - - migrations = Migrations("non_managed") - initial_orm = FakeORM(InitialMigration, "non_managed") - changes = AutoChanges( - migrations = migrations, - old_defs = self.full_defs, - old_orm = initial_orm, - new_defs = empty_defs, - ) - change_list = changes.get_changes() - if list(change_list): - self.fail("Auto migration deletes table for non-managed model") - - def test_not_modified_auto(self): - - fake_defs = { - 'non_managed.legacy': { - 'Meta': {'object_name': 'Legacy', 'db_table': "'legacy_table'", 'managed': 'False'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), - #'size': ('django.db.models.fields.IntegerField', [], {}) # The "change" is the addition of this field - } - } - class InitialMigration(SchemaMigration): - "Serves as fake previous migration" - - def forwards(self, orm): - pass - - def backwards(self, orm): - pass - - models = fake_defs - - complete_apps = ['non_managed'] - - from non_managed import models as dummy_import_to_force_loading_models # TODO: Does needing this indicate a bug in MokeyPatcher? - reload_module(dummy_import_to_force_loading_models) # really force... - - migrations = Migrations("non_managed") - initial_orm = FakeORM(InitialMigration, "non_managed") - changes = AutoChanges( - migrations = migrations, - old_defs = fake_defs, - old_orm = initial_orm, - new_defs = self.full_defs - ) - change_list = changes.get_changes() - if list(change_list): - self.fail("Auto migration changes table for non-managed model") diff --git a/lib/python2.7/site-packages/south/tests/brokenapp/__init__.py b/lib/python2.7/site-packages/south/tests/brokenapp/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/brokenapp/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0001_depends_on_unmigrated.py b/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0001_depends_on_unmigrated.py deleted file mode 100644 index d53f836..0000000 --- a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0001_depends_on_unmigrated.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('unknown', '0001_initial')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0002_depends_on_unknown.py b/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0002_depends_on_unknown.py deleted file mode 100644 index 389af80..0000000 --- a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0002_depends_on_unknown.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('fakeapp', '9999_unknown')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0003_depends_on_higher.py b/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0003_depends_on_higher.py deleted file mode 100644 index 319069b..0000000 --- a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0003_depends_on_higher.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('brokenapp', '0004_higher')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0004_higher.py b/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0004_higher.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/0004_higher.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/brokenapp/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/brokenapp/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/brokenapp/models.py b/lib/python2.7/site-packages/south/tests/brokenapp/models.py deleted file mode 100644 index a7d84dc..0000000 --- a/lib/python2.7/site-packages/south/tests/brokenapp/models.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: UTF-8 -*- - -from django.db import models -from django.contrib.auth.models import User as UserAlias - -def default_func(): - return "yays" - -# An empty case. -class Other1(models.Model): pass - -# Nastiness. -class HorribleModel(models.Model): - "A model to test the edge cases of model parsing" - - ZERO, ONE = range(2) - - # First, some nice fields - name = models.CharField(max_length=255) - short_name = models.CharField(max_length=50) - slug = models.SlugField(unique=True) - - # A ForeignKey, to a model above, and then below - o1 = models.ForeignKey(Other1) - o2 = models.ForeignKey('Other2') - - # Now to something outside - user = models.ForeignKey(UserAlias, related_name="horribles") - - # Unicode! - code = models.CharField(max_length=25, default="↑↑↓↓←→←→BA") - - # Odd defaults! - class_attr = models.IntegerField(default=ZERO) - func = models.CharField(max_length=25, default=default_func) - - # Time to get nasty. Define a non-field choices, and use it - choices = [('hello', '1'), ('world', '2')] - choiced = models.CharField(max_length=20, choices=choices) - - class Meta: - db_table = "my_fave" - verbose_name = "Dr. Strangelove," + \ - """or how I learned to stop worrying -and love the bomb""" - - # Now spread over multiple lines - multiline = \ - models.TextField( - ) - -# Special case. -class Other2(models.Model): - # Try loading a field without a newline after it (inspect hates this) - close_but_no_cigar = models.PositiveIntegerField(primary_key=True)
\ No newline at end of file diff --git a/lib/python2.7/site-packages/south/tests/circular_a/__init__.py b/lib/python2.7/site-packages/south/tests/circular_a/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_a/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/circular_a/migrations/0001_first.py b/lib/python2.7/site-packages/south/tests/circular_a/migrations/0001_first.py deleted file mode 100644 index b0d90eb..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_a/migrations/0001_first.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('circular_b', '0001_first')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/circular_a/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/circular_a/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_a/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/circular_a/models.py b/lib/python2.7/site-packages/south/tests/circular_a/models.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_a/models.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/circular_b/__init__.py b/lib/python2.7/site-packages/south/tests/circular_b/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_b/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/circular_b/migrations/0001_first.py b/lib/python2.7/site-packages/south/tests/circular_b/migrations/0001_first.py deleted file mode 100644 index b11b120..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_b/migrations/0001_first.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('circular_a', '0001_first')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/circular_b/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/circular_b/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_b/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/circular_b/models.py b/lib/python2.7/site-packages/south/tests/circular_b/models.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/circular_b/models.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/db.py b/lib/python2.7/site-packages/south/tests/db.py deleted file mode 100644 index e63c563..0000000 --- a/lib/python2.7/site-packages/south/tests/db.py +++ /dev/null @@ -1,1060 +0,0 @@ -import datetime -from warnings import filterwarnings - -from south.db import db, generic -from django.db import connection, models, IntegrityError as DjangoIntegrityError - -from south.tests import unittest, skipIf, skipUnless -from south.utils.py3 import text_type, with_metaclass - -# Create a list of error classes from the various database libraries -errors = [] -try: - from psycopg2 import ProgrammingError - errors.append(ProgrammingError) -except ImportError: - pass -errors = tuple(errors) - -# On SQL Server, the backend's IntegrityError is not (a subclass of) Django's. -try: - from sql_server.pyodbc.base import IntegrityError as SQLServerIntegrityError - IntegrityError = (DjangoIntegrityError, SQLServerIntegrityError) -except ImportError: - IntegrityError = DjangoIntegrityError - -try: - from south.db import mysql -except ImportError: - mysql = None - - -class TestOperations(unittest.TestCase): - - """ - Tests if the various DB abstraction calls work. - Can only test a limited amount due to DB differences. - """ - - def setUp(self): - db.debug = False - try: - import MySQLdb - except ImportError: - pass - else: - filterwarnings('ignore', category=MySQLdb.Warning) - db.clear_deferred_sql() - db.start_transaction() - - def tearDown(self): - db.rollback_transaction() - - def test_create(self): - """ - Test creation of tables. - """ - cursor = connection.cursor() - # It needs to take at least 2 args - self.assertRaises(TypeError, db.create_table) - self.assertRaises(TypeError, db.create_table, "test1") - # Empty tables (i.e. no columns) are not fine, so make at least 1 - db.create_table("test1", [('email_confirmed', models.BooleanField(default=False))]) - # And should exist - cursor.execute("SELECT * FROM test1") - # Make sure we can't do the same query on an empty table - try: - cursor.execute("SELECT * FROM nottheretest1") - except: - pass - else: - self.fail("Non-existent table could be selected!") - - @skipUnless(db.raises_default_errors, 'This database does not raise errors on missing defaults.') - def test_create_default(self): - """ - Test creation of tables, make sure defaults are not left in the database - """ - db.create_table("test_create_default", [('a', models.IntegerField()), - ('b', models.IntegerField(default=17))]) - cursor = connection.cursor() - self.assertRaises(IntegrityError, cursor.execute, "INSERT INTO test_create_default(a) VALUES (17)") - - def test_delete(self): - """ - Test deletion of tables. - """ - cursor = connection.cursor() - db.create_table("test_deltable", [('email_confirmed', models.BooleanField(default=False))]) - db.delete_table("test_deltable") - # Make sure it went - try: - cursor.execute("SELECT * FROM test_deltable") - except: - pass - else: - self.fail("Just-deleted table could be selected!") - - def test_nonexistent_delete(self): - """ - Test deletion of nonexistent tables. - """ - try: - db.delete_table("test_nonexistdeltable") - except: - pass - else: - self.fail("Non-existent table could be deleted!") - - def test_foreign_keys(self): - """ - Tests foreign key creation, especially uppercase (see #61) - """ - Test = db.mock_model(model_name='Test', db_table='test5a', - db_tablespace='', pk_field_name='ID', - pk_field_type=models.AutoField, pk_field_args=[]) - db.create_table("test5a", [('ID', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True))]) - db.create_table("test5b", [ - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('UNIQUE', models.ForeignKey(Test)), - ]) - db.execute_deferred_sql() - - @skipUnless(db.supports_foreign_keys, 'Foreign keys can only be deleted on ' - 'engines that support them.') - def test_recursive_foreign_key_delete(self): - """ - Test that recursive foreign keys are deleted correctly (see #1065) - """ - Test = db.mock_model(model_name='Test', db_table='test_rec_fk_del', - db_tablespace='', pk_field_name='id', - pk_field_type=models.AutoField, pk_field_args=[]) - db.create_table('test_rec_fk_del', [ - ('id', models.AutoField(primary_key=True, auto_created=True)), - ('fk', models.ForeignKey(Test)), - ]) - db.execute_deferred_sql() - db.delete_foreign_key('test_rec_fk_del', 'fk_id') - - def test_rename(self): - """ - Test column renaming - """ - cursor = connection.cursor() - db.create_table("test_rn", [('spam', models.BooleanField(default=False))]) - # Make sure we can select the column - cursor.execute("SELECT spam FROM test_rn") - # Rename it - db.rename_column("test_rn", "spam", "eggs") - cursor.execute("SELECT eggs FROM test_rn") - db.commit_transaction() - db.start_transaction() - try: - cursor.execute("SELECT spam FROM test_rn") - except: - pass - else: - self.fail("Just-renamed column could be selected!") - db.rollback_transaction() - db.delete_table("test_rn") - db.start_transaction() - - def test_dry_rename(self): - """ - Test column renaming while --dry-run is turned on (should do nothing) - See ticket #65 - """ - cursor = connection.cursor() - db.create_table("test_drn", [('spam', models.BooleanField(default=False))]) - # Make sure we can select the column - cursor.execute("SELECT spam FROM test_drn") - # Rename it - db.dry_run = True - db.rename_column("test_drn", "spam", "eggs") - db.dry_run = False - cursor.execute("SELECT spam FROM test_drn") - db.commit_transaction() - db.start_transaction() - try: - cursor.execute("SELECT eggs FROM test_drn") - except: - pass - else: - self.fail("Dry-renamed new column could be selected!") - db.rollback_transaction() - db.delete_table("test_drn") - db.start_transaction() - - def test_table_rename(self): - """ - Test column renaming - """ - cursor = connection.cursor() - db.create_table("testtr", [('spam', models.BooleanField(default=False))]) - # Make sure we can select the column - cursor.execute("SELECT spam FROM testtr") - # Rename it - db.rename_table("testtr", "testtr2") - cursor.execute("SELECT spam FROM testtr2") - db.commit_transaction() - db.start_transaction() - try: - cursor.execute("SELECT spam FROM testtr") - except: - pass - else: - self.fail("Just-renamed column could be selected!") - db.rollback_transaction() - db.delete_table("testtr2") - db.start_transaction() - - def test_percents_in_defaults(self): - """ - Test that % in a default gets escaped to %%. - """ - try: - db.create_table("testpind", [('cf', models.CharField(max_length=255, default="It should be 2%!"))]) - except IndexError: - self.fail("% was not properly escaped in column SQL.") - db.delete_table("testpind") - - def test_index(self): - """ - Test the index operations - """ - db.create_table("test3", [ - ('SELECT', models.BooleanField(default=False)), - ('eggs', models.IntegerField(unique=True)), - ]) - db.execute_deferred_sql() - # Add an index on that column - db.create_index("test3", ["SELECT"]) - # Add another index on two columns - db.create_index("test3", ["SELECT", "eggs"]) - # Delete them both - db.delete_index("test3", ["SELECT"]) - db.delete_index("test3", ["SELECT", "eggs"]) - # Delete the unique index/constraint - if db.backend_name != "sqlite3": - db.delete_unique("test3", ["eggs"]) - db.delete_table("test3") - - def test_primary_key(self): - """ - Test the primary key operations - """ - - db.create_table("test_pk", [ - ('id', models.IntegerField(primary_key=True)), - ('new_pkey', models.IntegerField()), - ('eggs', models.IntegerField(unique=True)), - ]) - db.execute_deferred_sql() - # Remove the default primary key, and make eggs it - db.delete_primary_key("test_pk") - db.create_primary_key("test_pk", "new_pkey") - # Try inserting a now-valid row pair - db.execute("INSERT INTO test_pk (id, new_pkey, eggs) VALUES (1, 2, 3)") - db.execute("INSERT INTO test_pk (id, new_pkey, eggs) VALUES (1, 3, 4)") - db.delete_table("test_pk") - - def test_primary_key_implicit(self): - """ - Tests that changing primary key implicitly fails. - """ - db.create_table("test_pki", [ - ('id', models.IntegerField(primary_key=True)), - ('new_pkey', models.IntegerField()), - ('eggs', models.IntegerField(unique=True)), - ]) - db.execute_deferred_sql() - # Fiddle with alter_column to attempt to make it remove the primary key - db.alter_column("test_pki", "id", models.IntegerField()) - db.alter_column("test_pki", "new_pkey", models.IntegerField(primary_key=True)) - # Try inserting a should-be-valid row pair - db.execute("INSERT INTO test_pki (id, new_pkey, eggs) VALUES (1, 2, 3)") - db.execute("INSERT INTO test_pki (id, new_pkey, eggs) VALUES (2, 2, 4)") - db.delete_table("test_pki") - - def test_add_columns(self): - """ - Test adding columns - """ - db.create_table("test_addc", [ - ('spam', models.BooleanField(default=False)), - ('eggs', models.IntegerField()), - ]) - # Add a column - db.add_column("test_addc", "add1", models.IntegerField(default=3)) - User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) - # insert some data so we can test the default value of the added fkey - db.execute("INSERT INTO test_addc (spam, eggs, add1) VALUES (%s, 1, 2)", [False]) - db.add_column("test_addc", "user", models.ForeignKey(User, null=True)) - db.execute_deferred_sql() - # try selecting from the user_id column to make sure it was actually created - val = db.execute("SELECT user_id FROM test_addc")[0][0] - self.assertEquals(val, None) - db.delete_column("test_addc", "add1") - # make sure adding an indexed field works - db.add_column("test_addc", "add2", models.CharField(max_length=15, db_index=True, default='pi')) - db.execute_deferred_sql() - db.delete_table("test_addc") - - def test_delete_columns(self): - """ - Test deleting columns - """ - db.create_table("test_delc", [ - ('spam', models.BooleanField(default=False)), - ('eggs', models.IntegerField(db_index=True, unique=True)), - ]) - db.delete_column("test_delc", "eggs") - - def test_add_nullbool_column(self): - """ - Test adding NullBoolean columns - """ - db.create_table("test_addnbc", [ - ('spam', models.BooleanField(default=False)), - ('eggs', models.IntegerField()), - ]) - # Add a column - db.add_column("test_addnbc", "add1", models.NullBooleanField()) - # Add a column with a default - db.add_column("test_addnbc", "add2", models.NullBooleanField(default=True)) - # insert some data so we can test the default values of the added column - db.execute("INSERT INTO test_addnbc (spam, eggs) VALUES (%s, 1)", [False]) - # try selecting from the new columns to make sure they were properly created - false, null1, null2 = db.execute("SELECT spam,add1,add2 FROM test_addnbc")[0][0:3] - self.assertIsNone(null1, "Null boolean field with no value inserted returns non-null") - self.assertIsNone(null2, "Null boolean field (added with default) with no value inserted returns non-null") - self.assertEquals(false, False) - db.delete_table("test_addnbc") - - def test_alter_columns(self): - """ - Test altering columns - """ - db.create_table("test_alterc", [ - ('spam', models.BooleanField(default=False)), - ('eggs', models.IntegerField()), - ]) - db.execute_deferred_sql() - # Change eggs to be a FloatField - db.alter_column("test_alterc", "eggs", models.FloatField()) - db.execute_deferred_sql() - db.delete_table("test_alterc") - db.execute_deferred_sql() - - def test_alter_char_default(self): - """ - Test altering column defaults with char fields - """ - db.create_table("test_altercd", [ - ('spam', models.CharField(max_length=30)), - ('eggs', models.IntegerField()), - ]) - # Change spam default - db.alter_column("test_altercd", "spam", models.CharField(max_length=30, default="loof", null=True)) - # Assert the default is not in the database - db.execute("INSERT INTO test_altercd (eggs) values (12)") - null = db.execute("SELECT spam FROM test_altercd")[0][0] - self.assertFalse(null, "Default for char field was installed into database") - - # Change again to a column with default and not null - db.alter_column("test_altercd", "spam", models.CharField(max_length=30, default="loof", null=False)) - # Assert the default is not in the database - if 'oracle' in db.backend_name: - # Oracle special treatment -- nulls are always allowed in char columns, so - # inserting doesn't raise an integrity error; so we check again as above - db.execute("DELETE FROM test_altercd") - db.execute("INSERT INTO test_altercd (eggs) values (12)") - null = db.execute("SELECT spam FROM test_altercd")[0][0] - self.assertFalse(null, "Default for char field was installed into database") - else: - # For other backends, insert should now just fail - self.assertRaises(IntegrityError, - db.execute, "INSERT INTO test_altercd (eggs) values (12)") - - @skipIf('oracle' in db.backend_name, "Oracle does not differentiate empty trings from null") - def test_default_empty_string(self): - """ - Test altering column defaults with char fields - """ - db.create_table("test_cd_empty", [ - ('spam', models.CharField(max_length=30, default='')), - ('eggs', models.CharField(max_length=30)), - ]) - # Create a record - db.execute("INSERT INTO test_cd_empty (spam, eggs) values ('1','2')") - # Add a column - db.add_column("test_cd_empty", "ham", models.CharField(max_length=30, default='')) - - empty = db.execute("SELECT ham FROM test_cd_empty")[0][0] - self.assertEquals(empty, "", "Empty Default for char field isn't empty string") - - @skipUnless('oracle' in db.backend_name, "Oracle does not differentiate empty trings from null") - def test_oracle_strings_null(self): - """ - Test that under Oracle, CherFields are created as null even when specified not-null, - because otherwise they would not be able to hold empty strings (which Oracle equates - with nulls). - Verify fix of #1269. - """ - db.create_table("test_ora_char_nulls", [ - ('spam', models.CharField(max_length=30, null=True)), - ('eggs', models.CharField(max_length=30)), - ]) - db.add_column("test_ora_char_nulls", "ham", models.CharField(max_length=30)) - db.alter_column("test_ora_char_nulls", "spam", models.CharField(max_length=30, null=False)) - # So, by the look of it, we should now have three not-null columns - db.execute("INSERT INTO test_ora_char_nulls VALUES (NULL, NULL, NULL)") - - - def test_mysql_defaults(self): - """ - Test MySQL default handling for BLOB and TEXT. - """ - db.create_table("test_altermyd", [ - ('spam', models.BooleanField(default=False)), - ('eggs', models.TextField()), - ]) - # Change eggs to be a FloatField - db.alter_column("test_altermyd", "eggs", models.TextField(null=True)) - db.delete_table("test_altermyd") - - def test_alter_column_postgres_multiword(self): - """ - Tests altering columns with multiple words in Postgres types (issue #125) - e.g. 'datetime with time zone', look at django/db/backends/postgresql/creation.py - """ - db.create_table("test_multiword", [ - ('col_datetime', models.DateTimeField(null=True)), - ('col_integer', models.PositiveIntegerField(null=True)), - ('col_smallint', models.PositiveSmallIntegerField(null=True)), - ('col_float', models.FloatField(null=True)), - ]) - - # test if 'double precision' is preserved - db.alter_column('test_multiword', 'col_float', models.FloatField('float', null=True)) - - # test if 'CHECK ("%(column)s" >= 0)' is stripped - db.alter_column('test_multiword', 'col_integer', models.PositiveIntegerField(null=True)) - db.alter_column('test_multiword', 'col_smallint', models.PositiveSmallIntegerField(null=True)) - - # test if 'with timezone' is preserved - if db.backend_name == "postgres": - db.execute("INSERT INTO test_multiword (col_datetime) VALUES ('2009-04-24 14:20:55+02')") - db.alter_column('test_multiword', 'col_datetime', models.DateTimeField(auto_now=True)) - assert db.execute("SELECT col_datetime = '2009-04-24 14:20:55+02' FROM test_multiword")[0][0] - - db.delete_table("test_multiword") - - @skipUnless(db.has_check_constraints, 'Only applies to databases that ' - 'support CHECK constraints.') - def test_alter_constraints(self): - """ - Tests that going from a PostiveIntegerField to an IntegerField drops - the constraint on the database. - """ - # Make the test table - db.create_table("test_alterc", [ - ('num', models.PositiveIntegerField()), - ]) - db.execute_deferred_sql() - # Add in some test values - db.execute("INSERT INTO test_alterc (num) VALUES (1)") - db.execute("INSERT INTO test_alterc (num) VALUES (2)") - # Ensure that adding a negative number is bad - db.commit_transaction() - db.start_transaction() - try: - db.execute("INSERT INTO test_alterc (num) VALUES (-3)") - except: - db.rollback_transaction() - else: - self.fail("Could insert a negative integer into a PositiveIntegerField.") - # Alter it to a normal IntegerField - db.alter_column("test_alterc", "num", models.IntegerField()) - db.execute_deferred_sql() - # It should now work - db.execute("INSERT INTO test_alterc (num) VALUES (-3)") - db.delete_table("test_alterc") - # We need to match up for tearDown - db.start_transaction() - - @skipIf(db.backend_name == "sqlite3", "SQLite backend doesn't support this " - "yet.") - def test_unique(self): - """ - Tests creating/deleting unique constraints. - """ - db.create_table("test_unique2", [ - ('id', models.AutoField(primary_key=True)), - ]) - db.create_table("test_unique", [ - ('spam', models.BooleanField(default=False)), - ('eggs', models.IntegerField()), - ('ham', models.ForeignKey(db.mock_model('Unique2', 'test_unique2'))), - ]) - db.execute_deferred_sql() - # Add a constraint - db.create_unique("test_unique", ["spam"]) - db.execute_deferred_sql() - # Shouldn't do anything during dry-run - db.dry_run = True - db.delete_unique("test_unique", ["spam"]) - db.dry_run = False - db.delete_unique("test_unique", ["spam"]) - db.create_unique("test_unique", ["spam"]) - # Special preparations for Sql Server - if db.backend_name == "pyodbc": - db.execute("SET IDENTITY_INSERT test_unique2 ON;") - db.execute("INSERT INTO test_unique2 (id) VALUES (1)") - db.execute("INSERT INTO test_unique2 (id) VALUES (2)") - db.commit_transaction() - db.start_transaction() - - - # Test it works - TRUE = (True,) - FALSE = (False,) - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 0, 1)", TRUE) - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 1, 2)", FALSE) - try: - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 2, 1)", FALSE) - except: - db.rollback_transaction() - else: - self.fail("Could insert non-unique item.") - - # Drop that, add one only on eggs - db.delete_unique("test_unique", ["spam"]) - db.execute("DELETE FROM test_unique") - db.create_unique("test_unique", ["eggs"]) - db.start_transaction() - - # Test similarly - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 0, 1)", TRUE) - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 1, 2)", FALSE) - try: - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 1, 1)", TRUE) - except: - db.rollback_transaction() - else: - self.fail("Could insert non-unique item.") - - # Drop those, test combined constraints - db.delete_unique("test_unique", ["eggs"]) - db.execute("DELETE FROM test_unique") - db.create_unique("test_unique", ["spam", "eggs", "ham_id"]) - db.start_transaction() - # Test similarly - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 0, 1)", TRUE) - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 1, 1)", FALSE) - try: - db.execute("INSERT INTO test_unique (spam, eggs, ham_id) VALUES (%s, 0, 1)", TRUE) - except: - db.rollback_transaction() - else: - self.fail("Could insert non-unique pair.") - db.delete_unique("test_unique", ["spam", "eggs", "ham_id"]) - db.start_transaction() - - def test_alter_unique(self): - """ - Tests that unique constraints are not affected when - altering columns (that's handled by create_/delete_unique) - """ - db.create_table("test_alter_unique", [ - ('spam', models.IntegerField()), - ('eggs', models.IntegerField(unique=True)), - ]) - db.execute_deferred_sql() - - # Make sure the unique constraint is created - db.execute('INSERT INTO test_alter_unique (spam, eggs) VALUES (0, 42)') - db.commit_transaction() - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique (spam, eggs) VALUES (1, 42)") - except: - pass - else: - self.fail("Could insert the same integer twice into a unique field.") - db.rollback_transaction() - - # Alter without unique=True (should not affect anything) - db.alter_column("test_alter_unique", "eggs", models.IntegerField()) - - # Insertion should still fail - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique (spam, eggs) VALUES (1, 42)") - except: - pass - else: - self.fail("Could insert the same integer twice into a unique field after alter_column with unique=False.") - db.rollback_transaction() - - # Delete the unique index/constraint - if db.backend_name != "sqlite3": - db.delete_unique("test_alter_unique", ["eggs"]) - db.delete_table("test_alter_unique") - db.start_transaction() - - # Test multi-field constraint - db.create_table("test_alter_unique2", [ - ('spam', models.IntegerField()), - ('eggs', models.IntegerField()), - ]) - db.create_unique('test_alter_unique2', ('spam', 'eggs')) - db.execute_deferred_sql() - db.execute('INSERT INTO test_alter_unique2 (spam, eggs) VALUES (0, 42)') - db.commit_transaction() - # Verify that constraint works - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique2 (spam, eggs) VALUES (1, 42)") - except: - self.fail("Looks like multi-field unique constraint applied to only one field.") - db.rollback_transaction() - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique2 (spam, eggs) VALUES (0, 43)") - except: - self.fail("Looks like multi-field unique constraint applied to only one field.") - db.rollback_transaction() - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique2 (spam, eggs) VALUES (0, 42)") - except: - pass - else: - self.fail("Could insert the same pair twice into unique-together fields.") - db.rollback_transaction() - # Altering one column should not drop or modify multi-column constraint - db.alter_column("test_alter_unique2", "eggs", models.PositiveIntegerField()) - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique2 (spam, eggs) VALUES (1, 42)") - except: - self.fail("Altering one column broken multi-column unique constraint.") - db.rollback_transaction() - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique2 (spam, eggs) VALUES (0, 43)") - except: - self.fail("Altering one column broken multi-column unique constraint.") - db.rollback_transaction() - db.start_transaction() - try: - db.execute("INSERT INTO test_alter_unique2 (spam, eggs) VALUES (0, 42)") - except: - pass - else: - self.fail("Could insert the same pair twice into unique-together fields after alter_column with unique=False.") - db.rollback_transaction() - db.delete_table("test_alter_unique2") - db.start_transaction() - - def test_capitalised_constraints(self): - """ - Under PostgreSQL at least, capitalised constraints must be quoted. - """ - db.create_table("test_capconst", [ - ('SOMECOL', models.PositiveIntegerField(primary_key=True)), - ]) - # Alter it so it's not got the check constraint - db.alter_column("test_capconst", "SOMECOL", models.IntegerField()) - - def test_text_default(self): - """ - MySQL cannot have blank defaults on TEXT columns. - """ - db.create_table("test_textdef", [ - ('textcol', models.TextField(blank=True)), - ]) - - def test_text_to_char(self): - """ - On Oracle, you can't simply ALTER TABLE MODIFY a textfield to a charfield - """ - value = "kawabanga" - db.create_table("test_text_to_char", [ - ('textcol', models.TextField()), - ]) - db.execute_deferred_sql() - db.execute("INSERT INTO test_text_to_char VALUES (%s)", [value]) - db.alter_column("test_text_to_char", "textcol", models.CharField(max_length=100)) - db.execute_deferred_sql() - after = db.execute("select * from test_text_to_char")[0][0] - self.assertEqual(value, after, "Change from text to char altered value [ %r != %r ]" % (value, after)) - - def test_char_to_text(self): - """ - On Oracle, you can't simply ALTER TABLE MODIFY a charfield to a textfield either - """ - value = "agnabawak" - db.create_table("test_char_to_text", [ - ('textcol', models.CharField(max_length=100)), - ]) - db.execute_deferred_sql() - db.execute("INSERT INTO test_char_to_text VALUES (%s)", [value]) - db.alter_column("test_char_to_text", "textcol", models.TextField()) - db.execute_deferred_sql() - after = db.execute("select * from test_char_to_text")[0][0] - after = text_type(after) # Oracle text fields return a sort of lazy string -- force evaluation - self.assertEqual(value, after, "Change from char to text altered value [ %r != %r ]" % (value, after)) - - @skipUnless(db.raises_default_errors, 'This database does not raise errors on missing defaults.') - def test_datetime_default(self): - """ - Test that defaults are correctly not created for datetime columns - """ - end_of_world = datetime.datetime(2012, 12, 21, 0, 0, 1) - - try: - from django.utils import timezone - except ImportError: - pass - else: - from django.conf import settings - if getattr(settings, 'USE_TZ', False): - end_of_world = end_of_world.replace(tzinfo=timezone.utc) - - db.create_table("test_datetime_def", [ - ('col0', models.IntegerField(null=True)), - ('col1', models.DateTimeField(default=end_of_world)), - ('col2', models.DateTimeField(null=True)), - ]) - db.execute_deferred_sql() - # insert a row - db.execute("INSERT INTO test_datetime_def (col0, col1, col2) values (null,%s,null)", [end_of_world]) - db.alter_column("test_datetime_def", "col2", models.DateTimeField(default=end_of_world)) - db.add_column("test_datetime_def", "col3", models.DateTimeField(default=end_of_world)) - db.execute_deferred_sql() - db.commit_transaction() - # In the single existing row, we now expect col1=col2=col3=end_of_world... - db.start_transaction() - ends = db.execute("select col1,col2,col3 from test_datetime_def")[0] - self.failUnlessEqual(len(ends), 3) - for e in ends: - self.failUnlessEqual(e, end_of_world) - db.commit_transaction() - # ...but there should not be a default in the database for col1 or col3 - for cols in ["col1,col2", "col2,col3"]: - db.start_transaction() - statement = "insert into test_datetime_def (col0,%s) values (null,%%s,%%s)" % cols - self.assertRaises( - IntegrityError, - db.execute, statement, [end_of_world, end_of_world] - ) - db.rollback_transaction() - - db.start_transaction() # To preserve the sanity and semantics of this test class - - def test_add_unique_fk(self): - """ - Test adding a ForeignKey with unique=True or a OneToOneField - """ - db.create_table("test_add_unique_fk", [ - ('spam', models.BooleanField(default=False)) - ]) - - db.add_column("test_add_unique_fk", "mock1", models.ForeignKey(db.mock_model('User', 'auth_user'), null=True, unique=True)) - db.add_column("test_add_unique_fk", "mock2", models.OneToOneField(db.mock_model('User', 'auth_user'), null=True)) - db.execute_deferred_sql() - - db.delete_table("test_add_unique_fk") - - @skipUnless(db.has_check_constraints, 'Only applies to databases that ' - 'support CHECK constraints.') - def test_column_constraint(self): - """ - Tests that the value constraint of PositiveIntegerField is enforced on - the database level. - """ - db.create_table("test_column_constraint", [ - ('spam', models.PositiveIntegerField()), - ]) - db.execute_deferred_sql() - - # Make sure we can't insert negative values - db.commit_transaction() - db.start_transaction() - try: - db.execute("INSERT INTO test_column_constraint VALUES (-42)") - except: - pass - else: - self.fail("Could insert a negative value into a PositiveIntegerField.") - db.rollback_transaction() - - # remove constraint - db.alter_column("test_column_constraint", "spam", models.IntegerField()) - db.execute_deferred_sql() - # make sure the insertion works now - db.execute('INSERT INTO test_column_constraint VALUES (-42)') - db.execute('DELETE FROM test_column_constraint') - - # add it back again - db.alter_column("test_column_constraint", "spam", models.PositiveIntegerField()) - db.execute_deferred_sql() - # it should fail again - db.start_transaction() - try: - db.execute("INSERT INTO test_column_constraint VALUES (-42)") - except: - pass - else: - self.fail("Could insert a negative value after changing an IntegerField to a PositiveIntegerField.") - db.rollback_transaction() - - db.delete_table("test_column_constraint") - db.start_transaction() - - def test_sql_defaults(self): - """ - Test that sql default value is correct for non-string field types. - Datetimes are handled in test_datetime_default. - """ - - class CustomField(with_metaclass(models.SubfieldBase, models.CharField)): - description = 'CustomField' - def get_default(self): - if self.has_default(): - if callable(self.default): - return self.default() - return self.default - return super(CustomField, self).get_default() - def get_prep_value(self, value): - if not value: - return value - return ','.join(map(str, value)) - def to_python(self, value): - if not value or isinstance(value, list): - return value - return list(map(int, value.split(','))) - - false_value = db.has_booleans and 'False' or '0' - defaults = ( - (models.CharField(default='sukasuka'), 'DEFAULT \'sukasuka'), - (models.BooleanField(default=False), 'DEFAULT %s' % false_value), - (models.IntegerField(default=42), 'DEFAULT 42'), - (CustomField(default=[2012, 2018, 2021, 2036]), 'DEFAULT \'2012,2018,2021,2036') - ) - for field, sql_test_str in defaults: - sql = db.column_sql('fish', 'YAAAAAAZ', field) - if sql_test_str not in sql: - self.fail("default sql value was not properly generated for field %r.\nSql was %s" % (field, sql)) - - def test_make_added_foreign_key_not_null(self): - # Table for FK to target - User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) - # Table with no foreign key - db.create_table("test_fk", [ - ('eggs', models.IntegerField()), - ]) - db.execute_deferred_sql() - - # Add foreign key - db.add_column("test_fk", 'foreik', models.ForeignKey(User, null=True)) - db.execute_deferred_sql() - - # Make the FK not null - db.alter_column("test_fk", "foreik_id", models.ForeignKey(User)) - db.execute_deferred_sql() - - def test_make_foreign_key_null(self): - # Table for FK to target - User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) - # Table with no foreign key - db.create_table("test_make_fk_null", [ - ('eggs', models.IntegerField()), - ('foreik', models.ForeignKey(User)) - ]) - db.execute_deferred_sql() - - # Make the FK null - db.alter_column("test_make_fk_null", "foreik_id", models.ForeignKey(User, null=True)) - db.execute_deferred_sql() - - def test_change_foreign_key_target(self): - # Tables for FK to target - User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) - db.create_table("test_fk_changed_target", [ - ('eggs', models.IntegerField(primary_key=True)), - ]) - Egg = db.mock_model(model_name='Egg', db_table='test_fk_changed_target', db_tablespace='', pk_field_name='eggs', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) - # Table with a foreign key to the wrong table - db.create_table("test_fk_changing", [ - ('egg', models.ForeignKey(User, null=True)), - ]) - db.execute_deferred_sql() - - # Change foreign key pointing - db.alter_column("test_fk_changing", "egg_id", models.ForeignKey(Egg, null=True)) - db.execute_deferred_sql() - - # Test that it is pointing at the right table now - try: - non_user_id = db.execute("SELECT MAX(id) FROM auth_user")[0][0] + 1 - except (TypeError, IndexError): - # Got a "None" or no records, treat as 0 - non_user_id = 17 - db.execute("INSERT INTO test_fk_changed_target (eggs) VALUES (%s)", [non_user_id]) - db.execute("INSERT INTO test_fk_changing (egg_id) VALUES (%s)", [non_user_id]) - db.commit_transaction() - db.start_transaction() # The test framework expects tests to end in transaction - - def test_alter_double_indexed_column(self): - # Table for FK to target - User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) - # Table with no foreign key - db.create_table("test_2indexed", [ - ('eggs', models.IntegerField()), - ('foreik', models.ForeignKey(User)) - ]) - db.create_unique("test_2indexed", ["eggs", "foreik_id"]) - db.execute_deferred_sql() - - # Make the FK null - db.alter_column("test_2indexed", "foreik_id", models.ForeignKey(User, null=True)) - db.execute_deferred_sql() - -class TestCacheGeneric(unittest.TestCase): - base_ops_cls = generic.DatabaseOperations - def setUp(self): - class CacheOps(self.base_ops_cls): - def __init__(self): - self._constraint_cache = {} - self.cache_filled = 0 - self.settings = {'NAME': 'db'} - - def _fill_constraint_cache(self, db, table): - self.cache_filled += 1 - self._constraint_cache.setdefault(db, {}) - self._constraint_cache[db].setdefault(table, {}) - - @generic.invalidate_table_constraints - def clear_con(self, table): - pass - - @generic.copy_column_constraints - def cp_column(self, table, column_old, column_new): - pass - - @generic.delete_column_constraints - def rm_column(self, table, column): - pass - - @generic.copy_column_constraints - @generic.delete_column_constraints - def mv_column(self, table, column_old, column_new): - pass - - def _get_setting(self, attr): - return self.settings[attr] - self.CacheOps = CacheOps - - def test_cache(self): - ops = self.CacheOps() - self.assertEqual(0, ops.cache_filled) - self.assertFalse(ops.lookup_constraint('db', 'table')) - self.assertEqual(1, ops.cache_filled) - self.assertFalse(ops.lookup_constraint('db', 'table')) - self.assertEqual(1, ops.cache_filled) - ops.clear_con('table') - self.assertEqual(1, ops.cache_filled) - self.assertFalse(ops.lookup_constraint('db', 'table')) - self.assertEqual(2, ops.cache_filled) - self.assertFalse(ops.lookup_constraint('db', 'table', 'column')) - self.assertEqual(2, ops.cache_filled) - - cache = ops._constraint_cache - cache['db']['table']['column'] = 'constraint' - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column')) - self.assertEqual([('column', 'constraint')], ops.lookup_constraint('db', 'table')) - self.assertEqual(2, ops.cache_filled) - - # invalidate_table_constraints - ops.clear_con('new_table') - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column')) - self.assertEqual(2, ops.cache_filled) - - self.assertFalse(ops.lookup_constraint('db', 'new_table')) - self.assertEqual(3, ops.cache_filled) - - # delete_column_constraints - cache['db']['table']['column'] = 'constraint' - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column')) - ops.rm_column('table', 'column') - self.assertEqual([], ops.lookup_constraint('db', 'table', 'column')) - self.assertEqual([], ops.lookup_constraint('db', 'table', 'noexist_column')) - - # copy_column_constraints - cache['db']['table']['column'] = 'constraint' - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column')) - ops.cp_column('table', 'column', 'column_new') - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column_new')) - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column')) - - # copy + delete - cache['db']['table']['column'] = 'constraint' - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column')) - ops.mv_column('table', 'column', 'column_new') - self.assertEqual('constraint', ops.lookup_constraint('db', 'table', 'column_new')) - self.assertEqual([], ops.lookup_constraint('db', 'table', 'column')) - - def test_valid(self): - ops = self.CacheOps() - # none of these should vivify a table into a valid state - self.assertFalse(ops._is_valid_cache('db', 'table')) - self.assertFalse(ops._is_valid_cache('db', 'table')) - ops.clear_con('table') - self.assertFalse(ops._is_valid_cache('db', 'table')) - ops.rm_column('table', 'column') - self.assertFalse(ops._is_valid_cache('db', 'table')) - - # these should change the cache state - ops.lookup_constraint('db', 'table') - self.assertTrue(ops._is_valid_cache('db', 'table')) - ops.lookup_constraint('db', 'table', 'column') - self.assertTrue(ops._is_valid_cache('db', 'table')) - ops.clear_con('table') - self.assertFalse(ops._is_valid_cache('db', 'table')) - - def test_valid_implementation(self): - # generic fills the cache on a per-table basis - ops = self.CacheOps() - self.assertFalse(ops._is_valid_cache('db', 'table')) - self.assertFalse(ops._is_valid_cache('db', 'other_table')) - ops.lookup_constraint('db', 'table') - self.assertTrue(ops._is_valid_cache('db', 'table')) - self.assertFalse(ops._is_valid_cache('db', 'other_table')) - ops.lookup_constraint('db', 'other_table') - self.assertTrue(ops._is_valid_cache('db', 'table')) - self.assertTrue(ops._is_valid_cache('db', 'other_table')) - ops.clear_con('table') - self.assertFalse(ops._is_valid_cache('db', 'table')) - self.assertTrue(ops._is_valid_cache('db', 'other_table')) - -if mysql: - class TestCacheMysql(TestCacheGeneric): - base_ops_cls = mysql.DatabaseOperations - - def test_valid_implementation(self): - # mysql fills the cache on a per-db basis - ops = self.CacheOps() - self.assertFalse(ops._is_valid_cache('db', 'table')) - self.assertFalse(ops._is_valid_cache('db', 'other_table')) - ops.lookup_constraint('db', 'table') - self.assertTrue(ops._is_valid_cache('db', 'table')) - self.assertTrue(ops._is_valid_cache('db', 'other_table')) - ops.lookup_constraint('db', 'other_table') - self.assertTrue(ops._is_valid_cache('db', 'table')) - self.assertTrue(ops._is_valid_cache('db', 'other_table')) - ops.clear_con('table') - self.assertFalse(ops._is_valid_cache('db', 'table')) - self.assertTrue(ops._is_valid_cache('db', 'other_table')) diff --git a/lib/python2.7/site-packages/south/tests/db_firebird.py b/lib/python2.7/site-packages/south/tests/db_firebird.py deleted file mode 100644 index 2b6bd53..0000000 --- a/lib/python2.7/site-packages/south/tests/db_firebird.py +++ /dev/null @@ -1,39 +0,0 @@ -from django.db import models - -from south.db import db -from south.tests import unittest, skipUnless - - -class FirebirdTests(unittest.TestCase): - - """ - Tests firebird related issues - """ - - def setUp(self): - print('=' * 80) - print('Begin Firebird test') - - def tearDown(self): - print('End Firebird test') - print('=' * 80) - - @skipUnless(db.backend_name == "firebird", "Firebird-only test") - def test_firebird_double_index_creation_1317(self): - """ - Tests foreign key creation, especially uppercase (see #61) - """ - Test = db.mock_model(model_name='Test', - db_table='test5a', - db_tablespace='', - pk_field_name='ID', - pk_field_type=models.AutoField, - pk_field_args=[] - ) - db.create_table("test5a", [('ID', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True))]) - db.create_table("test5b", [ - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('UNIQUE', models.ForeignKey(Test)), - ]) - db.execute_deferred_sql() - diff --git a/lib/python2.7/site-packages/south/tests/db_mysql.py b/lib/python2.7/site-packages/south/tests/db_mysql.py deleted file mode 100644 index e83596c..0000000 --- a/lib/python2.7/site-packages/south/tests/db_mysql.py +++ /dev/null @@ -1,164 +0,0 @@ -# Additional MySQL-specific tests -# Written by: F. Gabriel Gosselin <gabrielNOSPAM@evidens.ca> -# Based on tests by: aarranz -from south.tests import unittest, skipUnless - - -from south.db import db, generic, mysql -from django.db import connection, models - -from south.utils.py3 import with_metaclass - - -# A class decoration may be used in lieu of this when Python 2.5 is the -# minimum. -class TestMySQLOperationsMeta(type): - - def __new__(mcs, name, bases, dict_): - decorator = skipUnless(db.backend_name == "mysql", 'MySQL-specific tests') - - for key, method in dict_.items(): - if key.startswith('test'): - dict_[key] = decorator(method) - - return type.__new__(mcs, name, bases, dict_) - -class TestMySQLOperations(with_metaclass(TestMySQLOperationsMeta, unittest.TestCase)): - """MySQL-specific tests""" - - def setUp(self): - db.debug = False - db.clear_deferred_sql() - - def tearDown(self): - pass - - def _create_foreign_tables(self, main_name, reference_name): - # Create foreign table and model - Foreign = db.mock_model(model_name='Foreign', db_table=reference_name, - db_tablespace='', pk_field_name='id', - pk_field_type=models.AutoField, - pk_field_args=[]) - db.create_table(reference_name, [ - ('id', models.AutoField(primary_key=True)), - ]) - # Create table with foreign key - db.create_table(main_name, [ - ('id', models.AutoField(primary_key=True)), - ('foreign', models.ForeignKey(Foreign)), - ]) - return Foreign - - def test_constraint_references(self): - """Tests that referred table is reported accurately""" - main_table = 'test_cns_ref' - reference_table = 'test_cr_foreign' - db.start_transaction() - self._create_foreign_tables(main_table, reference_table) - db.execute_deferred_sql() - constraint = db._find_foreign_constraints(main_table, 'foreign_id')[0] - references = db._lookup_constraint_references(main_table, constraint) - self.assertEquals((reference_table, 'id'), references) - db.delete_table(main_table) - db.delete_table(reference_table) - - def test_reverse_column_constraint(self): - """Tests that referred column in a foreign key (ex. id) is found""" - main_table = 'test_reverse_ref' - reference_table = 'test_rr_foreign' - db.start_transaction() - self._create_foreign_tables(main_table, reference_table) - db.execute_deferred_sql() - inverse = db._lookup_reverse_constraint(reference_table, 'id') - (cname, rev_table, rev_column) = inverse[0] - self.assertEquals(main_table, rev_table) - self.assertEquals('foreign_id', rev_column) - db.delete_table(main_table) - db.delete_table(reference_table) - - def test_delete_fk_column(self): - main_table = 'test_drop_foreign' - ref_table = 'test_df_ref' - self._create_foreign_tables(main_table, ref_table) - db.execute_deferred_sql() - constraints = db._find_foreign_constraints(main_table, 'foreign_id') - self.assertEquals(len(constraints), 1) - db.delete_column(main_table, 'foreign_id') - constraints = db._find_foreign_constraints(main_table, 'foreign_id') - self.assertEquals(len(constraints), 0) - db.delete_table(main_table) - db.delete_table(ref_table) - - def test_rename_fk_column(self): - main_table = 'test_rename_foreign' - ref_table = 'test_rf_ref' - self._create_foreign_tables(main_table, ref_table) - db.execute_deferred_sql() - constraints = db._find_foreign_constraints(main_table, 'foreign_id') - self.assertEquals(len(constraints), 1) - db.rename_column(main_table, 'foreign_id', 'reference_id') - db.execute_deferred_sql() #Create constraints - constraints = db._find_foreign_constraints(main_table, 'reference_id') - self.assertEquals(len(constraints), 1) - db.delete_table(main_table) - db.delete_table(ref_table) - - def test_rename_fk_inbound(self): - """ - Tests that the column referred to by an external column can be renamed. - Edge case, but also useful as stepping stone to renaming tables. - """ - main_table = 'test_rename_fk_inbound' - ref_table = 'test_rfi_ref' - self._create_foreign_tables(main_table, ref_table) - db.execute_deferred_sql() - constraints = db._lookup_reverse_constraint(ref_table, 'id') - self.assertEquals(len(constraints), 1) - db.rename_column(ref_table, 'id', 'rfi_id') - db.execute_deferred_sql() #Create constraints - constraints = db._lookup_reverse_constraint(ref_table, 'rfi_id') - self.assertEquals(len(constraints), 1) - cname = db._find_foreign_constraints(main_table, 'foreign_id')[0] - (rtable, rcolumn) = db._lookup_constraint_references(main_table, cname) - self.assertEquals(rcolumn, 'rfi_id') - db.delete_table(main_table) - db.delete_table(ref_table) - - def test_rename_constrained_table(self): - """Renames a table with a foreign key column (towards another table)""" - main_table = 'test_rn_table' - ref_table = 'test_rt_ref' - renamed_table = 'test_renamed_table' - self._create_foreign_tables(main_table, ref_table) - db.execute_deferred_sql() - constraints = db._find_foreign_constraints(main_table, 'foreign_id') - self.assertEquals(len(constraints), 1) - db.rename_table(main_table, renamed_table) - db.execute_deferred_sql() #Create constraints - constraints = db._find_foreign_constraints(renamed_table, 'foreign_id') - self.assertEquals(len(constraints), 1) - (rtable, rcolumn) = db._lookup_constraint_references( - renamed_table, constraints[0]) - self.assertEquals(rcolumn, 'id') - db.delete_table(renamed_table) - db.delete_table(ref_table) - - def test_renamed_referenced_table(self): - """Rename a table referred to in a foreign key""" - main_table = 'test_rn_refd_table' - ref_table = 'test_rrt_ref' - renamed_table = 'test_renamed_ref' - self._create_foreign_tables(main_table, ref_table) - db.execute_deferred_sql() - constraints = db._lookup_reverse_constraint(ref_table) - self.assertEquals(len(constraints), 1) - db.rename_table(ref_table, renamed_table) - db.execute_deferred_sql() #Create constraints - constraints = db._find_foreign_constraints(main_table, 'foreign_id') - self.assertEquals(len(constraints), 1) - (rtable, rcolumn) = db._lookup_constraint_references( - main_table, constraints[0]) - self.assertEquals(renamed_table, rtable) - db.delete_table(main_table) - db.delete_table(renamed_table) - diff --git a/lib/python2.7/site-packages/south/tests/deps_a/__init__.py b/lib/python2.7/site-packages/south/tests/deps_a/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0001_a.py b/lib/python2.7/site-packages/south/tests/deps_a/migrations/0001_a.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0001_a.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0002_a.py b/lib/python2.7/site-packages/south/tests/deps_a/migrations/0002_a.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0002_a.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0003_a.py b/lib/python2.7/site-packages/south/tests/deps_a/migrations/0003_a.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0003_a.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0004_a.py b/lib/python2.7/site-packages/south/tests/deps_a/migrations/0004_a.py deleted file mode 100644 index e5c2977..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0004_a.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('deps_b', '0003_b')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0005_a.py b/lib/python2.7/site-packages/south/tests/deps_a/migrations/0005_a.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/migrations/0005_a.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_a/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/deps_a/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_a/models.py b/lib/python2.7/site-packages/south/tests/deps_a/models.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_a/models.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_b/__init__.py b/lib/python2.7/site-packages/south/tests/deps_b/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0001_b.py b/lib/python2.7/site-packages/south/tests/deps_b/migrations/0001_b.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0001_b.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0002_b.py b/lib/python2.7/site-packages/south/tests/deps_b/migrations/0002_b.py deleted file mode 100644 index 459ea5d..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0002_b.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('deps_a', '0002_a')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0003_b.py b/lib/python2.7/site-packages/south/tests/deps_b/migrations/0003_b.py deleted file mode 100644 index 1692888..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0003_b.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('deps_a', '0003_a')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0004_b.py b/lib/python2.7/site-packages/south/tests/deps_b/migrations/0004_b.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0004_b.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0005_b.py b/lib/python2.7/site-packages/south/tests/deps_b/migrations/0005_b.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/migrations/0005_b.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_b/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/deps_b/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_b/models.py b/lib/python2.7/site-packages/south/tests/deps_b/models.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_b/models.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_c/__init__.py b/lib/python2.7/site-packages/south/tests/deps_c/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0001_c.py b/lib/python2.7/site-packages/south/tests/deps_c/migrations/0001_c.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0001_c.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0002_c.py b/lib/python2.7/site-packages/south/tests/deps_c/migrations/0002_c.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0002_c.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0003_c.py b/lib/python2.7/site-packages/south/tests/deps_c/migrations/0003_c.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0003_c.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0004_c.py b/lib/python2.7/site-packages/south/tests/deps_c/migrations/0004_c.py deleted file mode 100644 index d27ed3a..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0004_c.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0005_c.py b/lib/python2.7/site-packages/south/tests/deps_c/migrations/0005_c.py deleted file mode 100644 index 459ea5d..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/migrations/0005_c.py +++ /dev/null @@ -1,13 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = [('deps_a', '0002_a')] - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/deps_c/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/deps_c/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/deps_c/models.py b/lib/python2.7/site-packages/south/tests/deps_c/models.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/deps_c/models.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/emptyapp/__init__.py b/lib/python2.7/site-packages/south/tests/emptyapp/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/emptyapp/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/emptyapp/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/emptyapp/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/emptyapp/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/emptyapp/models.py b/lib/python2.7/site-packages/south/tests/emptyapp/models.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/emptyapp/models.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/fakeapp/__init__.py b/lib/python2.7/site-packages/south/tests/fakeapp/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/fakeapp/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0001_spam.py b/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0001_spam.py deleted file mode 100644 index 9739648..0000000 --- a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0001_spam.py +++ /dev/null @@ -1,17 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - # Model 'Spam' - db.create_table("southtest_spam", ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('weight', models.FloatField()), - ('expires', models.DateTimeField()), - ('name', models.CharField(max_length=255)) - )) - - def backwards(self): - db.delete_table("southtest_spam") - diff --git a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0002_eggs.py b/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0002_eggs.py deleted file mode 100644 index 3ec8399..0000000 --- a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0002_eggs.py +++ /dev/null @@ -1,20 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - - Spam = db.mock_model(model_name='Spam', db_table='southtest_spam', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField) - - db.create_table("southtest_eggs", ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('size', models.FloatField()), - ('quantity', models.IntegerField()), - ('spam', models.ForeignKey(Spam)), - )) - - def backwards(self): - - db.delete_table("southtest_eggs") - diff --git a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0003_alter_spam.py b/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0003_alter_spam.py deleted file mode 100644 index 39126c2..0000000 --- a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/0003_alter_spam.py +++ /dev/null @@ -1,18 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - - db.alter_column("southtest_spam", 'weight', models.FloatField(null=True)) - - def backwards(self): - - db.alter_column("southtest_spam", 'weight', models.FloatField()) - - models = { - "fakeapp.bug135": { - 'date': ('models.DateTimeField', [], {'default': 'datetime.datetime(2009, 5, 6, 15, 33, 15, 780013)'}), - } - } diff --git a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/fakeapp/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/fakeapp/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/fakeapp/models.py b/lib/python2.7/site-packages/south/tests/fakeapp/models.py deleted file mode 100644 index cc39eb7..0000000 --- a/lib/python2.7/site-packages/south/tests/fakeapp/models.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- coding: UTF-8 -*- - -from django.db import models -from django.contrib.auth.models import User as UserAlias - -from south.modelsinspector import add_introspection_rules - -on_delete_is_available = hasattr(models, "PROTECT") # models here is django.db.models - -def default_func(): - return "yays" - -# An empty case. -class Other1(models.Model): pass - -# Another one -class Other3(models.Model): pass -def get_sentinel_object(): - """ - A function to return the object to be used in place of any deleted object, - when using the SET option for on_delete. - """ - # Create a new one, so we always have an instance to test with. Can't work! - return Other3() - -# Nastiness. -class HorribleModel(models.Model): - "A model to test the edge cases of model parsing" - - ZERO, ONE = 0, 1 - - # First, some nice fields - name = models.CharField(max_length=255) - short_name = models.CharField(max_length=50) - slug = models.SlugField(unique=True) - - # A ForeignKey, to a model above, and then below - o1 = models.ForeignKey(Other1) - o2 = models.ForeignKey('Other2') - - if on_delete_is_available: - o_set_null_on_delete = models.ForeignKey('Other3', null=True, on_delete=models.SET_NULL) - o_cascade_delete = models.ForeignKey('Other3', null=True, on_delete=models.CASCADE, related_name="cascademe") - o_protect = models.ForeignKey('Other3', null=True, on_delete=models.PROTECT, related_name="dontcascademe") - o_default_on_delete = models.ForeignKey('Other3', null=True, default=1, on_delete=models.SET_DEFAULT, related_name="setmedefault") - o_set_on_delete_function = models.ForeignKey('Other3', null=True, default=1, on_delete=models.SET(get_sentinel_object), related_name="setsentinel") - o_set_on_delete_value = models.ForeignKey('Other3', null=True, default=1, on_delete=models.SET(get_sentinel_object()), related_name="setsentinelwithactualvalue") # dubious case - o_no_action_on_delete = models.ForeignKey('Other3', null=True, default=1, on_delete=models.DO_NOTHING, related_name="deletemeatyourperil") - - - # Now to something outside - user = models.ForeignKey(UserAlias, related_name="horribles") - - # Unicode! - code = models.CharField(max_length=25, default="↑↑↓↓←→←→BA") - - # Odd defaults! - class_attr = models.IntegerField(default=ZERO) - func = models.CharField(max_length=25, default=default_func) - - # Time to get nasty. Define a non-field choices, and use it - choices = [('hello', '1'), ('world', '2')] - choiced = models.CharField(max_length=20, choices=choices) - - class Meta: - db_table = "my_fave" - verbose_name = "Dr. Strangelove," + \ - """or how I learned to stop worrying -and love the bomb""" - - # Now spread over multiple lines - multiline = \ - models.TextField( - ) - -# Special case. -class Other2(models.Model): - # Try loading a field without a newline after it (inspect hates this) - close_but_no_cigar = models.PositiveIntegerField(primary_key=True) - -class CustomField(models.IntegerField): - def __init__(self, an_other_model, **kwargs): - super(CustomField, self).__init__(**kwargs) - self.an_other_model = an_other_model - -add_introspection_rules([ - ( - [CustomField], - [], - {'an_other_model': ('an_other_model', {})}, - ), -], ['^south\.tests\.fakeapp\.models\.CustomField']) - -class BaseModel(models.Model): - pass - -class SubModel(BaseModel): - others = models.ManyToManyField(Other1) - custom = CustomField(Other2) - -class CircularA(models.Model): - c = models.ForeignKey('CircularC') - -class CircularB(models.Model): - a = models.ForeignKey(CircularA) - -class CircularC(models.Model): - b = models.ForeignKey(CircularB) - -class Recursive(models.Model): - self = models.ForeignKey('self') diff --git a/lib/python2.7/site-packages/south/tests/freezer.py b/lib/python2.7/site-packages/south/tests/freezer.py deleted file mode 100644 index 82c4402..0000000 --- a/lib/python2.7/site-packages/south/tests/freezer.py +++ /dev/null @@ -1,15 +0,0 @@ -from south.tests import unittest - -from south.creator.freezer import model_dependencies -from south.tests.fakeapp import models - -class TestFreezer(unittest.TestCase): - def test_dependencies(self): - self.assertEqual(set(model_dependencies(models.SubModel)), - set([models.BaseModel, models.Other1, models.Other2])) - - self.assertEqual(set(model_dependencies(models.CircularA)), - set([models.CircularA, models.CircularB, models.CircularC])) - - self.assertEqual(set(model_dependencies(models.Recursive)), - set([models.Recursive])) diff --git a/lib/python2.7/site-packages/south/tests/inspector.py b/lib/python2.7/site-packages/south/tests/inspector.py deleted file mode 100644 index dcd6d57..0000000 --- a/lib/python2.7/site-packages/south/tests/inspector.py +++ /dev/null @@ -1,109 +0,0 @@ - -from south.tests import Monkeypatcher, skipUnless -from south.modelsinspector import (convert_on_delete_handler, get_value, - IsDefault, models, value_clean) - -from fakeapp.models import HorribleModel, get_sentinel_object - - -on_delete_is_available = hasattr(models, "PROTECT") # models here is django.db.models -skipUnlessOnDeleteAvailable = skipUnless(on_delete_is_available, "not testing on_delete -- not available on Django<1.3") - -class TestModelInspector(Monkeypatcher): - - """ - Tests if the various parts of the modelinspector work. - """ - - def test_get_value(self): - - # Let's start nicely. - name = HorribleModel._meta.get_field_by_name("name")[0] - slug = HorribleModel._meta.get_field_by_name("slug")[0] - user = HorribleModel._meta.get_field_by_name("user")[0] - - # Simple int retrieval - self.assertEqual( - get_value(name, ["max_length", {}]), - "255", - ) - - # Bool retrieval - self.assertEqual( - get_value(slug, ["unique", {}]), - "True", - ) - - # String retrieval - self.assertEqual( - get_value(user, ["rel.related_name", {}]), - "'horribles'", - ) - - # Default triggering - self.assertEqual( - get_value(slug, ["unique", {"default": False}]), - "True", - ) - self.assertRaises( - IsDefault, - get_value, - slug, - ["unique", {"default": True}], - ) - - @skipUnlessOnDeleteAvailable - def test_get_value_on_delete(self): - - # First validate the FK fields with on_delete options - o_set_null_on_delete = HorribleModel._meta.get_field_by_name("o_set_null_on_delete")[0] - o_cascade_delete = HorribleModel._meta.get_field_by_name("o_cascade_delete")[0] - o_protect = HorribleModel._meta.get_field_by_name("o_protect")[0] - o_default_on_delete = HorribleModel._meta.get_field_by_name("o_default_on_delete")[0] - o_set_on_delete_function = HorribleModel._meta.get_field_by_name("o_set_on_delete_function")[0] - o_set_on_delete_value = HorribleModel._meta.get_field_by_name("o_set_on_delete_value")[0] - o_no_action_on_delete = HorribleModel._meta.get_field_by_name("o_no_action_on_delete")[0] - # TODO this is repeated from the introspection_details in modelsinspector: - # better to refactor that so we can reference these settings, in case they - # must change at some point. - on_delete = ["rel.on_delete", {"default": models.CASCADE, "is_django_function": True, "converter": convert_on_delete_handler, }] - - # Foreign Key cascade update/delete - self.assertRaises( - IsDefault, - get_value, - o_cascade_delete, - on_delete, - ) - self.assertEqual( - get_value(o_protect, on_delete), - "models.PROTECT", - ) - self.assertEqual( - get_value(o_no_action_on_delete, on_delete), - "models.DO_NOTHING", - ) - self.assertEqual( - get_value(o_set_null_on_delete, on_delete), - "models.SET_NULL", - ) - self.assertEqual( - get_value(o_default_on_delete, on_delete), - "models.SET_DEFAULT", - ) - # For now o_set_on_delete raises, see modelsinspector.py - #self.assertEqual( - # get_value(o_set_on_delete_function, on_delete), - # "models.SET(get_sentinel_object)", - #) - self.assertRaises( - ValueError, - get_value, - o_set_on_delete_function, - on_delete, - ) - self.assertEqual( - get_value(o_set_on_delete_value, on_delete), - "models.SET(%s)" % value_clean(get_sentinel_object()), - ) -
\ No newline at end of file diff --git a/lib/python2.7/site-packages/south/tests/logger.py b/lib/python2.7/site-packages/south/tests/logger.py deleted file mode 100644 index 78d159d..0000000 --- a/lib/python2.7/site-packages/south/tests/logger.py +++ /dev/null @@ -1,82 +0,0 @@ -import io -import logging -import os -import tempfile -from south.tests import unittest -import sys - -from django.conf import settings -from django.db import connection, models - -from south.db import db -from south.logger import close_logger - -class TestLogger(unittest.TestCase): - - """ - Tests if the logging is working reasonably. Some tests ignored if you don't - have write permission to the disk. - """ - - def setUp(self): - db.debug = False - self.test_path = tempfile.mkstemp(suffix=".south.log")[1] - - def test_db_execute_logging_nofile(self): - "Does logging degrade nicely if SOUTH_LOGGING_ON not set?" - settings.SOUTH_LOGGING_ON = False # this needs to be set to False - # to avoid issues where other tests - # set this to True. settings is shared - # between these tests. - db.create_table("test9", [('email_confirmed', models.BooleanField(default=False))]) - - def test_db_execute_logging_off_with_basic_config(self): - """ - Does the south logger avoid outputing debug information with - south logging turned off and python logging configured with - a basic config?" - """ - settings.SOUTH_LOGGING_ON = False - - # Set root logger to capture WARNING and worse - logging_stream = io.StringIO() - logging.basicConfig(stream=logging_stream, level=logging.WARNING) - - db.create_table("test12", [('email_confirmed', models.BooleanField(default=False))]) - - # since south logging is off, and our root logger is at WARNING - # we should not find DEBUG info in the log - self.assertEqual(logging_stream.getvalue(), '') - - def test_db_execute_logging_validfile(self): - "Does logging work when passing in a valid file?" - settings.SOUTH_LOGGING_ON = True - settings.SOUTH_LOGGING_FILE = self.test_path - # Check to see if we can make the logfile - try: - fh = open(self.test_path, "w") - except IOError: - # Permission was denied, ignore the test. - return - else: - fh.close() - # Do an action which logs - db.create_table("test10", [('email_confirmed', models.BooleanField(default=False))]) - # Close the logged file - close_logger() - try: - os.remove(self.test_path) - except: - # It's a tempfile, it's not vital we remove it. - pass - - def test_db_execute_logging_missingfilename(self): - "Does logging raise an error if there is a missing filename?" - settings.SOUTH_LOGGING_ON = True - settings.SOUTH_LOGGING_FILE = None - self.assertRaises( - IOError, - db.create_table, - "test11", - [('email_confirmed', models.BooleanField(default=False))], - ) diff --git a/lib/python2.7/site-packages/south/tests/logic.py b/lib/python2.7/site-packages/south/tests/logic.py deleted file mode 100644 index 2b21cef..0000000 --- a/lib/python2.7/site-packages/south/tests/logic.py +++ /dev/null @@ -1,902 +0,0 @@ -from south.tests import unittest - -import datetime -import sys -try: - set # builtin, python >=2.6 -except NameError: - from sets import Set as set # in stdlib, python >=2.3 - -from south import exceptions -from south.migration import migrate_app -from south.migration.base import all_migrations, Migrations -from south.creator.changes import ManualChanges -from south.migration.utils import depends, flatten, get_app_label -from south.models import MigrationHistory -from south.tests import Monkeypatcher -from south.db import db - - - -class TestBrokenMigration(Monkeypatcher): - installed_apps = ["fakeapp", "otherfakeapp", "brokenapp"] - - def test_broken_dependencies(self): - self.assertRaises( - exceptions.DependsOnUnmigratedApplication, - Migrations.calculate_dependencies, - force=True, - ) - #depends_on_unknown = self.brokenapp['0002_depends_on_unknown'] - #self.assertRaises(exceptions.DependsOnUnknownMigration, - # depends_on_unknown.dependencies) - #depends_on_higher = self.brokenapp['0003_depends_on_higher'] - #self.assertRaises(exceptions.DependsOnHigherMigration, - # depends_on_higher.dependencies) - - -class TestMigration(Monkeypatcher): - installed_apps = ["fakeapp", "otherfakeapp"] - - def setUp(self): - super(TestMigration, self).setUp() - self.fakeapp = Migrations('fakeapp') - self.otherfakeapp = Migrations('otherfakeapp') - Migrations.calculate_dependencies(force=True) - - def test_str(self): - migrations = [str(m) for m in self.fakeapp] - self.assertEqual(['fakeapp:0001_spam', - 'fakeapp:0002_eggs', - 'fakeapp:0003_alter_spam'], - migrations) - - def test_repr(self): - migrations = [repr(m) for m in self.fakeapp] - self.assertEqual(['<Migration: fakeapp:0001_spam>', - '<Migration: fakeapp:0002_eggs>', - '<Migration: fakeapp:0003_alter_spam>'], - migrations) - - def test_app_label(self): - self.assertEqual(['fakeapp', 'fakeapp', 'fakeapp'], - [m.app_label() for m in self.fakeapp]) - - def test_name(self): - self.assertEqual(['0001_spam', '0002_eggs', '0003_alter_spam'], - [m.name() for m in self.fakeapp]) - - def test_full_name(self): - self.assertEqual(['fakeapp.migrations.0001_spam', - 'fakeapp.migrations.0002_eggs', - 'fakeapp.migrations.0003_alter_spam'], - [m.full_name() for m in self.fakeapp]) - - def test_migration(self): - # Can't use vanilla import, modules beginning with numbers aren't in grammar - M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration - M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration - M3 = __import__("fakeapp.migrations.0003_alter_spam", {}, {}, ['Migration']).Migration - self.assertEqual([M1, M2, M3], - [m.migration().Migration for m in self.fakeapp]) - self.assertRaises(exceptions.UnknownMigration, - self.fakeapp['9999_unknown'].migration) - - def test_previous(self): - self.assertEqual([None, - self.fakeapp['0001_spam'], - self.fakeapp['0002_eggs']], - [m.previous() for m in self.fakeapp]) - - def test_dependencies(self): - "Test that the dependency detection works." - self.assertEqual([ - set([]), - set([self.fakeapp['0001_spam']]), - set([self.fakeapp['0002_eggs']]) - ], - [m.dependencies for m in self.fakeapp], - ) - self.assertEqual([ - set([self.fakeapp['0001_spam']]), - set([self.otherfakeapp['0001_first']]), - set([ - self.otherfakeapp['0002_second'], - self.fakeapp['0003_alter_spam'], - ]) - ], - [m.dependencies for m in self.otherfakeapp], - ) - - def test_forwards_plan(self): - self.assertEqual([ - [self.fakeapp['0001_spam']], - [ - self.fakeapp['0001_spam'], - self.fakeapp['0002_eggs'] - ], - [ - self.fakeapp['0001_spam'], - self.fakeapp['0002_eggs'], - self.fakeapp['0003_alter_spam'], - ] - ], - [m.forwards_plan() for m in self.fakeapp], - ) - self.assertEqual([ - [ - self.fakeapp['0001_spam'], - self.otherfakeapp['0001_first'] - ], - [ - self.fakeapp['0001_spam'], - self.otherfakeapp['0001_first'], - self.otherfakeapp['0002_second'] - ], - [ - self.fakeapp['0001_spam'], - self.otherfakeapp['0001_first'], - self.otherfakeapp['0002_second'], - self.fakeapp['0002_eggs'], - self.fakeapp['0003_alter_spam'], - self.otherfakeapp['0003_third'], - ] - ], - [m.forwards_plan() for m in self.otherfakeapp], - ) - - def test_is_before(self): - F1 = self.fakeapp['0001_spam'] - F2 = self.fakeapp['0002_eggs'] - F3 = self.fakeapp['0003_alter_spam'] - O1 = self.otherfakeapp['0001_first'] - O2 = self.otherfakeapp['0002_second'] - O3 = self.otherfakeapp['0003_third'] - self.assertTrue(F1.is_before(F2)) - self.assertTrue(F1.is_before(F3)) - self.assertTrue(F2.is_before(F3)) - self.assertEqual(O3.is_before(O1), False) - self.assertEqual(O3.is_before(O2), False) - self.assertEqual(O2.is_before(O2), False) - self.assertEqual(O2.is_before(O1), False) - self.assertEqual(F2.is_before(O1), None) - self.assertEqual(F2.is_before(O2), None) - self.assertEqual(F2.is_before(O3), None) - - -class TestMigrationDependencies(Monkeypatcher): - installed_apps = ['deps_a', 'deps_b', 'deps_c'] - - def setUp(self): - super(TestMigrationDependencies, self).setUp() - self.deps_a = Migrations('deps_a') - self.deps_b = Migrations('deps_b') - self.deps_c = Migrations('deps_c') - Migrations.calculate_dependencies(force=True) - - def test_dependencies(self): - self.assertEqual( - [ - set([]), - set([self.deps_a['0001_a']]), - set([self.deps_a['0002_a']]), - set([ - self.deps_a['0003_a'], - self.deps_b['0003_b'], - ]), - set([self.deps_a['0004_a']]), - ], - [m.dependencies for m in self.deps_a], - ) - self.assertEqual( - [ - set([]), - set([ - self.deps_b['0001_b'], - self.deps_a['0002_a'] - ]), - set([ - self.deps_b['0002_b'], - self.deps_a['0003_a'] - ]), - set([self.deps_b['0003_b']]), - set([self.deps_b['0004_b']]), - ], - [m.dependencies for m in self.deps_b], - ) - self.assertEqual( - [ - set([]), - set([self.deps_c['0001_c']]), - set([self.deps_c['0002_c']]), - set([self.deps_c['0003_c']]), - set([ - self.deps_c['0004_c'], - self.deps_a['0002_a'] - ]), - ], - [m.dependencies for m in self.deps_c], - ) - - def test_dependents(self): - self.assertEqual([set([self.deps_a['0002_a']]), - set([self.deps_c['0005_c'], - self.deps_b['0002_b'], - self.deps_a['0003_a']]), - set([self.deps_b['0003_b'], - self.deps_a['0004_a']]), - set([self.deps_a['0005_a']]), - set([])], - [m.dependents for m in self.deps_a]) - self.assertEqual([set([self.deps_b['0002_b']]), - set([self.deps_b['0003_b']]), - set([self.deps_b['0004_b'], - self.deps_a['0004_a']]), - set([self.deps_b['0005_b']]), - set([])], - [m.dependents for m in self.deps_b]) - self.assertEqual([set([self.deps_c['0002_c']]), - set([self.deps_c['0003_c']]), - set([self.deps_c['0004_c']]), - set([self.deps_c['0005_c']]), - set([])], - [m.dependents for m in self.deps_c]) - - def test_forwards_plan(self): - self.assertEqual([[self.deps_a['0001_a']], - [self.deps_a['0001_a'], - self.deps_a['0002_a']], - [self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_a['0003_a']], - [self.deps_b['0001_b'], - self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_b['0002_b'], - self.deps_a['0003_a'], - self.deps_b['0003_b'], - self.deps_a['0004_a']], - [self.deps_b['0001_b'], - self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_b['0002_b'], - self.deps_a['0003_a'], - self.deps_b['0003_b'], - self.deps_a['0004_a'], - self.deps_a['0005_a']]], - [m.forwards_plan() for m in self.deps_a]) - self.assertEqual([[self.deps_b['0001_b']], - [self.deps_b['0001_b'], - self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_b['0002_b']], - [self.deps_b['0001_b'], - self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_b['0002_b'], - self.deps_a['0003_a'], - self.deps_b['0003_b']], - [self.deps_b['0001_b'], - self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_b['0002_b'], - self.deps_a['0003_a'], - self.deps_b['0003_b'], - self.deps_b['0004_b']], - [self.deps_b['0001_b'], - self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_b['0002_b'], - self.deps_a['0003_a'], - self.deps_b['0003_b'], - self.deps_b['0004_b'], - self.deps_b['0005_b']]], - [m.forwards_plan() for m in self.deps_b]) - self.assertEqual([[self.deps_c['0001_c']], - [self.deps_c['0001_c'], - self.deps_c['0002_c']], - [self.deps_c['0001_c'], - self.deps_c['0002_c'], - self.deps_c['0003_c']], - [self.deps_c['0001_c'], - self.deps_c['0002_c'], - self.deps_c['0003_c'], - self.deps_c['0004_c']], - [self.deps_c['0001_c'], - self.deps_c['0002_c'], - self.deps_c['0003_c'], - self.deps_c['0004_c'], - self.deps_a['0001_a'], - self.deps_a['0002_a'], - self.deps_c['0005_c']]], - [m.forwards_plan() for m in self.deps_c]) - - def test_backwards_plan(self): - self.assertEqual([ - [ - self.deps_c['0005_c'], - self.deps_b['0005_b'], - self.deps_b['0004_b'], - self.deps_a['0005_a'], - self.deps_a['0004_a'], - self.deps_b['0003_b'], - self.deps_b['0002_b'], - self.deps_a['0003_a'], - self.deps_a['0002_a'], - self.deps_a['0001_a'], - ], - [ - self.deps_c['0005_c'], - self.deps_b['0005_b'], - self.deps_b['0004_b'], - self.deps_a['0005_a'], - self.deps_a['0004_a'], - self.deps_b['0003_b'], - self.deps_b['0002_b'], - self.deps_a['0003_a'], - self.deps_a['0002_a'], - ], - [ - self.deps_b['0005_b'], - self.deps_b['0004_b'], - self.deps_a['0005_a'], - self.deps_a['0004_a'], - self.deps_b['0003_b'], - self.deps_a['0003_a'], - ], - [ - self.deps_a['0005_a'], - self.deps_a['0004_a'], - ], - [ - self.deps_a['0005_a'], - ] - ], [m.backwards_plan() for m in self.deps_a]) - self.assertEqual([ - [ - self.deps_b['0005_b'], - self.deps_b['0004_b'], - self.deps_a['0005_a'], - self.deps_a['0004_a'], - self.deps_b['0003_b'], - self.deps_b['0002_b'], - self.deps_b['0001_b'], - ], - [ - self.deps_b['0005_b'], - self.deps_b['0004_b'], - self.deps_a['0005_a'], - self.deps_a['0004_a'], - self.deps_b['0003_b'], - self.deps_b['0002_b'], - ], - [ - self.deps_b['0005_b'], - self.deps_b['0004_b'], - self.deps_a['0005_a'], - self.deps_a['0004_a'], - self.deps_b['0003_b'], - ], - [ - self.deps_b['0005_b'], - self.deps_b['0004_b'], - ], - [ - self.deps_b['0005_b'], - ], - ], [m.backwards_plan() for m in self.deps_b]) - self.assertEqual([ - [ - self.deps_c['0005_c'], - self.deps_c['0004_c'], - self.deps_c['0003_c'], - self.deps_c['0002_c'], - self.deps_c['0001_c'], - ], - [ - self.deps_c['0005_c'], - self.deps_c['0004_c'], - self.deps_c['0003_c'], - self.deps_c['0002_c'], - ], - [ - self.deps_c['0005_c'], - self.deps_c['0004_c'], - self.deps_c['0003_c'], - ], - [ - self.deps_c['0005_c'], - self.deps_c['0004_c'], - ], - [self.deps_c['0005_c']] - ], [m.backwards_plan() for m in self.deps_c]) - - -class TestCircularDependencies(Monkeypatcher): - installed_apps = ["circular_a", "circular_b"] - - def test_plans(self): - Migrations.calculate_dependencies(force=True) - circular_a = Migrations('circular_a') - circular_b = Migrations('circular_b') - self.assertRaises( - exceptions.CircularDependency, - circular_a[-1].forwards_plan, - ) - self.assertRaises( - exceptions.CircularDependency, - circular_b[-1].forwards_plan, - ) - self.assertRaises( - exceptions.CircularDependency, - circular_a[-1].backwards_plan, - ) - self.assertRaises( - exceptions.CircularDependency, - circular_b[-1].backwards_plan, - ) - - -class TestMigrations(Monkeypatcher): - installed_apps = ["fakeapp", "otherfakeapp"] - - def test_all(self): - - M1 = Migrations(__import__("fakeapp", {}, {}, [''])) - M2 = Migrations(__import__("otherfakeapp", {}, {}, [''])) - - self.assertEqual( - [M1, M2], - list(all_migrations()), - ) - - def test(self): - - M1 = Migrations(__import__("fakeapp", {}, {}, [''])) - - self.assertEqual(M1, Migrations("fakeapp")) - self.assertEqual(M1, Migrations(self.create_fake_app("fakeapp"))) - - def test_application(self): - fakeapp = Migrations("fakeapp") - application = __import__("fakeapp", {}, {}, ['']) - self.assertEqual(application, fakeapp.application) - - def test_migration(self): - # Can't use vanilla import, modules beginning with numbers aren't in grammar - M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration - M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration - migration = Migrations('fakeapp') - self.assertEqual(M1, migration['0001_spam'].migration().Migration) - self.assertEqual(M2, migration['0002_eggs'].migration().Migration) - self.assertRaises(exceptions.UnknownMigration, - migration['0001_jam'].migration) - - def test_guess_migration(self): - # Can't use vanilla import, modules beginning with numbers aren't in grammar - M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration - migration = Migrations('fakeapp') - self.assertEqual(M1, migration.guess_migration("0001_spam").migration().Migration) - self.assertEqual(M1, migration.guess_migration("0001_spa").migration().Migration) - self.assertEqual(M1, migration.guess_migration("0001_sp").migration().Migration) - self.assertEqual(M1, migration.guess_migration("0001_s").migration().Migration) - self.assertEqual(M1, migration.guess_migration("0001_").migration().Migration) - self.assertEqual(M1, migration.guess_migration("0001").migration().Migration) - self.assertRaises(exceptions.UnknownMigration, - migration.guess_migration, "0001-spam") - self.assertRaises(exceptions.MultiplePrefixMatches, - migration.guess_migration, "000") - self.assertRaises(exceptions.MultiplePrefixMatches, - migration.guess_migration, "") - self.assertRaises(exceptions.UnknownMigration, - migration.guess_migration, "0001_spams") - self.assertRaises(exceptions.UnknownMigration, - migration.guess_migration, "0001_jam") - - def test_app_label(self): - names = ['fakeapp', 'otherfakeapp'] - self.assertEqual(names, - [Migrations(n).app_label() for n in names]) - - def test_full_name(self): - names = ['fakeapp', 'otherfakeapp'] - self.assertEqual([n + '.migrations' for n in names], - [Migrations(n).full_name() for n in names]) - - -class TestMigrationLogic(Monkeypatcher): - - """ - Tests if the various logic functions in migration actually work. - """ - - installed_apps = ["fakeapp", "otherfakeapp"] - - def setUp(self): - super(TestMigrationLogic, self).setUp() - MigrationHistory.objects.all().delete() - - def assertListEqual(self, list1, list2, msg=None): - list1 = set(list1) - list2 = set(list2) - return self.assert_(list1 == list2, "%s is not equal to %s" % (list1, list2)) - - def test_find_ghost_migrations(self): - pass - - def test_apply_migrations(self): - migrations = Migrations("fakeapp") - - # We should start with no migrations - self.assertEqual(list(MigrationHistory.objects.all()), []) - - # Apply them normally - migrate_app(migrations, target_name=None, fake=False, - load_initial_data=True) - - # We should finish with all migrations - self.assertListEqual( - (("fakeapp", "0001_spam"), - ("fakeapp", "0002_eggs"), - ("fakeapp", "0003_alter_spam"),), - MigrationHistory.objects.values_list("app_name", "migration"), - ) - - # Now roll them backwards - migrate_app(migrations, target_name="zero", fake=False) - - # Finish with none - self.assertEqual(list(MigrationHistory.objects.all()), []) - - - def test_migration_merge_forwards(self): - migrations = Migrations("fakeapp") - - # We should start with no migrations - self.assertEqual(list(MigrationHistory.objects.all()), []) - - # Insert one in the wrong order - MigrationHistory.objects.create(app_name = "fakeapp", - migration = "0002_eggs", - applied = datetime.datetime.now()) - - # Did it go in? - self.assertListEqual( - (("fakeapp", "0002_eggs"),), - MigrationHistory.objects.values_list("app_name", "migration"), - ) - - # Apply them normally - self.assertRaises(exceptions.InconsistentMigrationHistory, - migrate_app, - migrations, target_name=None, fake=False) - self.assertRaises(exceptions.InconsistentMigrationHistory, - migrate_app, - migrations, target_name='zero', fake=False) - try: - migrate_app(migrations, target_name=None, fake=False) - except exceptions.InconsistentMigrationHistory as e: - self.assertEqual( - [ - ( - migrations['0002_eggs'], - migrations['0001_spam'], - ) - ], - e.problems, - ) - try: - migrate_app(migrations, target_name="zero", fake=False) - except exceptions.InconsistentMigrationHistory as e: - self.assertEqual( - [ - ( - migrations['0002_eggs'], - migrations['0001_spam'], - ) - ], - e.problems, - ) - - # Nothing should have changed (no merge mode!) - self.assertListEqual( - (("fakeapp", "0002_eggs"),), - MigrationHistory.objects.values_list("app_name", "migration"), - ) - - # Apply with merge - migrate_app(migrations, target_name=None, merge=True, fake=False) - - # We should finish with all migrations - self.assertListEqual( - (("fakeapp", "0001_spam"), - ("fakeapp", "0002_eggs"), - ("fakeapp", "0003_alter_spam"),), - MigrationHistory.objects.values_list("app_name", "migration"), - ) - - # Now roll them backwards - migrate_app(migrations, target_name="0002", fake=False) - migrate_app(migrations, target_name="0001", fake=True) - migrate_app(migrations, target_name="zero", fake=False) - - # Finish with none - self.assertEqual(list(MigrationHistory.objects.all()), []) - - def test_alter_column_null(self): - - def null_ok(eat_exception=True): - from django.db import connection, transaction - # the DBAPI introspection module fails on postgres NULLs. - cursor = connection.cursor() - - # SQLite has weird now() - if db.backend_name == "sqlite3": - now_func = "DATETIME('NOW')" - # So does SQLServer... should we be using a backend attribute? - elif db.backend_name == "pyodbc": - now_func = "GETDATE()" - elif db.backend_name == "oracle": - now_func = "SYSDATE" - else: - now_func = "NOW()" - - try: - if db.backend_name == "pyodbc": - cursor.execute("SET IDENTITY_INSERT southtest_spam ON;") - cursor.execute("INSERT INTO southtest_spam (id, weight, expires, name) VALUES (100, NULL, %s, 'whatever');" % now_func) - except: - if eat_exception: - transaction.rollback() - return False - else: - raise - else: - cursor.execute("DELETE FROM southtest_spam") - transaction.commit() - return True - - MigrationHistory.objects.all().delete() - migrations = Migrations("fakeapp") - - # by default name is NOT NULL - migrate_app(migrations, target_name="0002", fake=False) - self.failIf(null_ok()) - self.assertListEqual( - (("fakeapp", "0001_spam"), - ("fakeapp", "0002_eggs"),), - MigrationHistory.objects.values_list("app_name", "migration"), - ) - - # after 0003, it should be NULL - migrate_app(migrations, target_name="0003", fake=False) - self.assert_(null_ok(False)) - self.assertListEqual( - (("fakeapp", "0001_spam"), - ("fakeapp", "0002_eggs"), - ("fakeapp", "0003_alter_spam"),), - MigrationHistory.objects.values_list("app_name", "migration"), - ) - - # make sure it is NOT NULL again - migrate_app(migrations, target_name="0002", fake=False) - self.failIf(null_ok(), 'weight not null after migration') - self.assertListEqual( - (("fakeapp", "0001_spam"), - ("fakeapp", "0002_eggs"),), - MigrationHistory.objects.values_list("app_name", "migration"), - ) - - # finish with no migrations, otherwise other tests fail... - migrate_app(migrations, target_name="zero", fake=False) - self.assertEqual(list(MigrationHistory.objects.all()), []) - - def test_dependencies(self): - - fakeapp = Migrations("fakeapp") - otherfakeapp = Migrations("otherfakeapp") - - # Test a simple path - self.assertEqual([fakeapp['0001_spam'], - fakeapp['0002_eggs'], - fakeapp['0003_alter_spam']], - fakeapp['0003_alter_spam'].forwards_plan()) - - # And a complex one. - self.assertEqual( - [ - fakeapp['0001_spam'], - otherfakeapp['0001_first'], - otherfakeapp['0002_second'], - fakeapp['0002_eggs'], - fakeapp['0003_alter_spam'], - otherfakeapp['0003_third'] - ], - otherfakeapp['0003_third'].forwards_plan(), - ) - - -class TestMigrationUtils(Monkeypatcher): - installed_apps = ["fakeapp", "otherfakeapp"] - - def test_get_app_label(self): - self.assertEqual( - "southtest", - get_app_label(self.create_fake_app("southtest.models")), - ) - self.assertEqual( - "baz", - get_app_label(self.create_fake_app("foo.bar.baz.models")), - ) - -class TestUtils(unittest.TestCase): - - def test_flatten(self): - self.assertEqual([], list(flatten(iter([])))) - self.assertEqual([], list(flatten(iter([iter([]), ])))) - self.assertEqual([1], list(flatten(iter([1])))) - self.assertEqual([1, 2], list(flatten(iter([1, 2])))) - self.assertEqual([1, 2], list(flatten(iter([iter([1]), 2])))) - self.assertEqual([1, 2], list(flatten(iter([iter([1, 2])])))) - self.assertEqual([1, 2, 3], list(flatten(iter([iter([1, 2]), 3])))) - self.assertEqual([1, 2, 3], - list(flatten(iter([iter([1]), iter([2]), 3])))) - self.assertEqual([1, 2, 3], - list(flatten([[1], [2], 3]))) - - def test_depends(self): - graph = {'A1': []} - self.assertEqual(['A1'], - depends('A1', lambda n: graph[n])) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2']} - self.assertEqual(['A1', 'A2', 'A3'], - depends('A3', lambda n: graph[n])) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2', 'A1']} - self.assertEqual(['A1', 'A2', 'A3'], - depends('A3', lambda n: graph[n])) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2', 'A1', 'B1'], - 'B1': []} - self.assertEqual( - ['B1', 'A1', 'A2', 'A3'], - depends('A3', lambda n: graph[n]), - ) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2', 'A1', 'B2'], - 'B1': [], - 'B2': ['B1']} - self.assertEqual( - ['B1', 'B2', 'A1', 'A2', 'A3'], - depends('A3', lambda n: graph[n]), - ) - graph = {'A1': [], - 'A2': ['A1', 'B1'], - 'A3': ['A2'], - 'B1': ['A1']} - self.assertEqual(['A1', 'B1', 'A2', 'A3'], - depends('A3', lambda n: graph[n])) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2', 'A1', 'B2'], - 'B1': [], - 'B2': ['B1', 'C1'], - 'C1': ['B1']} - self.assertEqual( - ['B1', 'C1', 'B2', 'A1', 'A2', 'A3'], - depends('A3', lambda n: graph[n]), - ) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2', 'B2', 'A1', 'C1'], - 'B1': ['A1'], - 'B2': ['B1', 'C2', 'A1'], - 'C1': ['B1'], - 'C2': ['C1', 'A1'], - 'C3': ['C2']} - self.assertEqual( - ['A1', 'B1', 'C1', 'C2', 'B2', 'A2', 'A3'], - depends('A3', lambda n: graph[n]), - ) - - def assertCircularDependency(self, trace, target, graph): - "Custom assertion that checks a circular dependency is detected correctly." - self.assertRaises( - exceptions.CircularDependency, - depends, - target, - lambda n: graph[n], - ) - try: - depends(target, lambda n: graph[n]) - except exceptions.CircularDependency as e: - self.assertEqual(trace, e.trace) - - def test_depends_cycle(self): - graph = {'A1': ['A1']} - self.assertCircularDependency( - ['A1', 'A1'], - 'A1', - graph, - ) - graph = {'A1': [], - 'A2': ['A1', 'A2'], - 'A3': ['A2']} - self.assertCircularDependency( - ['A2', 'A2'], - 'A3', - graph, - ) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2', 'A3'], - 'A4': ['A3']} - self.assertCircularDependency( - ['A3', 'A3'], - 'A4', - graph, - ) - graph = {'A1': ['B1'], - 'B1': ['A1']} - self.assertCircularDependency( - ['A1', 'B1', 'A1'], - 'A1', - graph, - ) - graph = {'A1': [], - 'A2': ['A1', 'B2'], - 'A3': ['A2'], - 'B1': [], - 'B2': ['B1', 'A2'], - 'B3': ['B2']} - self.assertCircularDependency( - ['A2', 'B2', 'A2'], - 'A3', - graph, - ) - graph = {'A1': [], - 'A2': ['A1', 'B3'], - 'A3': ['A2'], - 'B1': [], - 'B2': ['B1', 'A2'], - 'B3': ['B2']} - self.assertCircularDependency( - ['A2', 'B3', 'B2', 'A2'], - 'A3', - graph, - ) - graph = {'A1': [], - 'A2': ['A1'], - 'A3': ['A2', 'B2'], - 'A4': ['A3'], - 'B1': ['A3'], - 'B2': ['B1']} - self.assertCircularDependency( - ['A3', 'B2', 'B1', 'A3'], - 'A4', - graph, - ) - -class TestManualChanges(Monkeypatcher): - installed_apps = ["fakeapp", "otherfakeapp"] - - def test_suggest_name(self): - migrations = Migrations('fakeapp') - change = ManualChanges(migrations, - [], - ['fakeapp.slug'], - []) - self.assertEquals(change.suggest_name(), - 'add_field_fakeapp_slug') - - change = ManualChanges(migrations, - [], - [], - ['fakeapp.slug']) - self.assertEquals(change.suggest_name(), - 'add_index_fakeapp_slug') diff --git a/lib/python2.7/site-packages/south/tests/non_managed/__init__.py b/lib/python2.7/site-packages/south/tests/non_managed/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/non_managed/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/non_managed/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/non_managed/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/non_managed/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/non_managed/models.py b/lib/python2.7/site-packages/south/tests/non_managed/models.py deleted file mode 100644 index e520d94..0000000 --- a/lib/python2.7/site-packages/south/tests/non_managed/models.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: UTF-8 -*- - -""" -An app with a model that is not managed for testing that South does -not try to manage it in any way -""" -from django.db import models - -class Legacy(models.Model): - - name = models.CharField(max_length=10) - size = models.IntegerField() - - class Meta: - db_table = "legacy_table" - managed = False diff --git a/lib/python2.7/site-packages/south/tests/otherfakeapp/__init__.py b/lib/python2.7/site-packages/south/tests/otherfakeapp/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/otherfakeapp/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0001_first.py b/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0001_first.py deleted file mode 100644 index ad9c095..0000000 --- a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0001_first.py +++ /dev/null @@ -1,15 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = ( - ("fakeapp", "0001_spam"), - ) - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0002_second.py b/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0002_second.py deleted file mode 100644 index 7c0fb0c..0000000 --- a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0002_second.py +++ /dev/null @@ -1,11 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - def forwards(self): - pass - - def backwards(self): - pass - diff --git a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0003_third.py b/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0003_third.py deleted file mode 100644 index fa8ed97..0000000 --- a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/0003_third.py +++ /dev/null @@ -1,14 +0,0 @@ -from south.db import db -from django.db import models - -class Migration: - - depends_on = ( - ("fakeapp", "0003_alter_spam"), - ) - - def forwards(self): - pass - - def backwards(self): - pass diff --git a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/__init__.py b/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lib/python2.7/site-packages/south/tests/otherfakeapp/migrations/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/south/tests/otherfakeapp/models.py b/lib/python2.7/site-packages/south/tests/otherfakeapp/models.py deleted file mode 100644 index 93a4b8e..0000000 --- a/lib/python2.7/site-packages/south/tests/otherfakeapp/models.py +++ /dev/null @@ -1 +0,0 @@ -# This file left intentionally blank.
\ No newline at end of file diff --git a/lib/python2.7/site-packages/south/utils/__init__.py b/lib/python2.7/site-packages/south/utils/__init__.py deleted file mode 100644 index 8d7297e..0000000 --- a/lib/python2.7/site-packages/south/utils/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -""" -Generally helpful utility functions. -""" - - -def _ask_for_it_by_name(name): - "Returns an object referenced by absolute path." - bits = str(name).split(".") - - ## what if there is no absolute reference? - if len(bits) > 1: - modulename = ".".join(bits[:-1]) - else: - modulename = bits[0] - - module = __import__(modulename, {}, {}, bits[-1]) - - if len(bits) == 1: - return module - else: - return getattr(module, bits[-1]) - - -def ask_for_it_by_name(name): - "Returns an object referenced by absolute path. (Memoised outer wrapper)" - if name not in ask_for_it_by_name.cache: - ask_for_it_by_name.cache[name] = _ask_for_it_by_name(name) - return ask_for_it_by_name.cache[name] -ask_for_it_by_name.cache = {} - - -def get_attribute(item, attribute): - """ - Like getattr, but recursive (i.e. you can ask for 'foo.bar.yay'.) - """ - value = item - for part in attribute.split("."): - value = getattr(value, part) - return value - -def auto_through(field): - "Returns if the M2M class passed in has an autogenerated through table or not." - return ( - # Django 1.0/1.1 - (not field.rel.through) - or - # Django 1.2+ - getattr(getattr(field.rel.through, "_meta", None), "auto_created", False) - ) - -def auto_model(model): - "Returns if the given model was automatically generated." - return getattr(model._meta, "auto_created", False) - -def memoize(function): - "Standard memoization decorator." - name = function.__name__ - _name = '_' + name - - def method(self): - if not hasattr(self, _name): - value = function(self) - setattr(self, _name, value) - return getattr(self, _name) - - def invalidate(): - if hasattr(method, _name): - delattr(method, _name) - - method.__name__ = function.__name__ - method.__doc__ = function.__doc__ - method._invalidate = invalidate - return method diff --git a/lib/python2.7/site-packages/south/utils/datetime_utils.py b/lib/python2.7/site-packages/south/utils/datetime_utils.py deleted file mode 100644 index a416935..0000000 --- a/lib/python2.7/site-packages/south/utils/datetime_utils.py +++ /dev/null @@ -1,28 +0,0 @@ -from datetime import * - -import django -from django.conf import settings - -if django.VERSION[:2] >= (1, 4) and getattr(settings, 'USE_TZ', False): - from django.utils import timezone - from datetime import datetime as _datetime - - class datetime(_datetime): - """ - A custom datetime.datetime class which acts as a compatibility - layer between South and Django 1.4's timezone aware datetime - instances. - - It basically adds the default timezone (as configured in Django's - settings) automatically if no tzinfo is given. - """ - def __new__(cls, year, month, day, - hour=0, minute=0, second=0, microsecond=0, tzinfo=None): - - dt = _datetime(year, month, day, - hour, minute, second, microsecond, - tzinfo=tzinfo) - if tzinfo is None: - default_timezone = timezone.get_default_timezone() - dt = timezone.make_aware(dt, default_timezone) - return dt diff --git a/lib/python2.7/site-packages/south/utils/py3.py b/lib/python2.7/site-packages/south/utils/py3.py deleted file mode 100644 index 732e904..0000000 --- a/lib/python2.7/site-packages/south/utils/py3.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Python 2 + 3 compatibility functions. This is a very small subset of six. -""" - -import sys - -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - text_type = str - raw_input = input - - import io - StringIO = io.StringIO - -else: - string_types = basestring, - text_type = unicode - raw_input = raw_input - - import cStringIO - StringIO = cStringIO.StringIO - - -def with_metaclass(meta, base=object): - """Create a base class with a metaclass.""" - return meta("NewBase", (base,), {}) diff --git a/lib/python2.7/site-packages/south/v2.py b/lib/python2.7/site-packages/south/v2.py deleted file mode 100644 index 22afed2..0000000 --- a/lib/python2.7/site-packages/south/v2.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -API versioning file; we can tell what kind of migrations things are -by what class they inherit from (if none, it's a v1). -""" - -from south.utils import ask_for_it_by_name - -class BaseMigration(object): - - def gf(self, field_name): - "Gets a field by absolute reference." - field = ask_for_it_by_name(field_name) - field.model = FakeModel - return field - -class SchemaMigration(BaseMigration): - pass - -class DataMigration(BaseMigration): - # Data migrations shouldn't be dry-run - no_dry_run = True - -class FakeModel(object): - "Fake model so error messages on fields don't explode" - pass |