Commits

Anonymous committed 344a367 Merge

merge svn trunk incluing ver 0.4 release

Comments (0)

Files changed (8)

 South - Useable migrations for Django apps
 """
 
-__version__ = "0.3"
-__authors__ = ["Andrew Godwin <andrew@aeracode.org>", "Andy McCurdy <andy@andymccurdy.com>"]
+__version__ = "0.4"
+__authors__ = ["Andrew Godwin <andrew@aeracode.org>", "Andy McCurdy <andy@andymccurdy.com>"]
         self.debug = False
         self.deferred_sql = []
         self.dry_run = False
+        self.pending_create_signals = []
 
     def execute(self, sql, params=[]):
         """
         Resets the deferred_sql list to empty.
         """
         self.deferred_sql = []
+    
+    
+    def clear_run_data(self):
+        """
+        Resets variables to how they should be before a run. Used for dry runs.
+        """
+        self.clear_deferred_sql()
+        self.pending_create_signals = []
 
 
     def create_table(self, table_name, fields):
             # this allows the addition of a NOT NULL field to a table with existing rows
             if not field.null and field.has_default():
                 default = field.get_default()
+                # 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, basestring):
                     default = "'%s'" % default.replace("'", "''")
                 elif isinstance(default, datetime.date):
 
 
     def send_create_signal(self, app_label, model_names):
+        self.pending_create_signals.append((app_label, model_names))
+
+
+    def send_pending_create_signals(self):
+        for (app_label, model_names) in self.pending_create_signals:
+            self.really_send_create_signal(app_label, model_names)
+        self.pending_create_signals = []
+
+
+    def really_send_create_signal(self, app_label, model_names):
         """
         Sends a post_syncdb signal for the model specified.
 
         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

db/postgresql_psycopg2.py

         try:
             generic.DatabaseOperations.rename_table(self, old_table_name+"_id_seq", table_name+"_id_seq")
         except:
-            print "   ~ No such sequence (ignoring error)"
-            self.rollback_transaction()
-        else:
-            self.commit_transaction()
-        self.start_transaction()
-        # rename primary key, will not rename other indices on the table that are used by django (e.g. foreign keys)
-        try:
-            generic.DatabaseOperations.rename_table(self, old_table_name+"_pkey", table_name+ "_pkey")
-        except:
-            print "   ~ No such primary key (ignoring error)"
+            if self.debug:
+                print "   ~ No such sequence (ignoring error)"
             self.rollback_transaction()
         else:
             self.commit_transaction()
         self.start_transaction()
 
+        # 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.
+        try:
+            generic.DatabaseOperations.rename_table(self, old_table_name+"_pkey", table_name+ "_pkey")
+        except:
+            if self.debug:
+                print "   ~ No such primary key (ignoring error)"
+            self.rollback_transaction()
+        else:
+            self.commit_transaction()
+        self.start_transaction()
+
 
     def rename_index(self, old_index_name, index_name):
-        "use to rename an index individually"
+        "Rename an index individually"
         generic.DatabaseOperations.rename_table(self, old_index_name, index_name)
             self.create_index(table_name, [name], unique=True)
     
     # SQLite doesn't have ALTER COLUMN
-    def alter_column(self, table_name, name, field):
+    def alter_column(self, table_name, name, field, explicit_name=True):
         """
         Not supported under SQLite.
         """

install/README

-To use this setup.py, make sure you checked out this trunk or branch into a directory called 'south', copy the setup.py into the directory above it, and off you go.

install/setup.py

-#!/usr/bin/python
-
-from setuptools import setup, find_packages
-
-setup(
-    name='South',
-    version='0.3',
-    description='South: Migrations for Django',
-    author='Andrew Godwin & Andy McCurdy',
-    author_email='south@aeracode.org',
-    url='http://south.aeracode.org/',
-    packages=["south", "south.db", "south.management", "south.management.commands", "south.tests"],
-)
                     print " ! Error found during dry run of migration! Aborting."
                     return False
                 db.debug = old_debug
-                db.clear_deferred_sql()
+                db.clear_run_data()
             
             db.dry_run = bool(db_dry_run)
             
     if direction == 1:
         if not silent:
             print " - Migrating forwards to %s." % target_name
-        for mapp, mname in forwards:
-            if (mapp, mname) not in current_migrations:
-                result = run_forwards(mapp, [mname], fake=fake, db_dry_run=db_dry_run, silent=silent)
-                if result is False: # The migrations errored, but nicely.
-                    return
+        try:
+            for mapp, mname in forwards:
+                if (mapp, mname) not in current_migrations:
+                    result = run_forwards(mapp, [mname], fake=fake, db_dry_run=db_dry_run, silent=silent)
+                    if result is False: # The migrations errored, but nicely.
+                        return
+        finally:
+            # Call any pending post_syncdb signals
+            db.send_pending_create_signals()
         # Now load initial data, only if we're really doing things and ended up at current
         if not fake and not db_dry_run and load_inital_data and target_name == migrations[-1]:
             print " - Loading initial data for %s." % app_name
 
 setup(
     name='South',
-    version='0.3',
+    version='0.4',
     description='South: Migrations for Django',
+    long_description='South is an intelligent database migrations library for the Django web framework. It is database-independent and DVCS-friendly, as well as a whole host of other features.',
     author='Andrew Godwin & Andy McCurdy',
     author_email='south@aeracode.org',
     url='http://south.aeracode.org/',
+    download_url='http://south.aeracode.org/wiki/Download',
+    classifiers=[
+        "Development Status :: 5 - Production/Stable",
+        "Framework :: Django",
+        "Intended Audience :: Developers",
+        "Intended Audience :: System Administrators",
+        "Intended Audience :: System Administrators",
+        "License :: OSI Approved :: Apache Software License",
+        "Operating System :: OS Independent",
+        "Topic :: Software Development"
+    ],
     packages=["south", "south.db", "south.management", "south.management.commands", "south.tests", "south.tests.fakeapp", "south.tests.fakeapp.migrations"],
     package_dir = {"south" : ""},
 )