Index: termcolors.py
===================================================================
--- termcolors.py	(revision 0)
+++ termcolors.py	(revision 0)
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+
+"""
+termcolors.py
+
+set termcolors.DISABLE = True to disable the whole shebang
+"""
+import types
+
+colour_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta',
+        'cyan', 'white')
+foreground = {}; background = {}
+[ foreground.update({colour_names[x]: '3%s' % x}) for x in range(8) ]
+[ background.update({colour_names[x]: '4%s' % x}) for x in range(8) ]
+
+RESET, BOLD, UNDERSCORE, BLINK, REVERSE, CONCEAL = '014578'
+opt_dict = {'bold': BOLD, 'underscore': UNDERSCORE, 'blink': BLINK,
+        'reverse': REVERSE, 'conceal': CONCEAL,}
+
+DISABLE = False
+
+def gfx(text='', opts=(), **kwargs):
+    """Returns your text, enclosed in ANSI graphics codes
+    
+Depends on the keyword arguments 'fgcol' and 'bgcol', and the contents of the
+opts tuple/list
+
+With no parameters is a special case - it returns the RESET code
+
+Valid colours:
+    'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
+    
+Valid options:
+    'bold'
+    'underscore'
+    'blink'
+    'reverse'
+    'conceal'
+    'noreset' - string will not be auto-terminated with the RESET code
+
+Examples:
+    gfx('hello', fgcol='red', bgcol='blue', opts=('blink',))
+    gfx()
+    gfx('goodbye', opts=('underscore',))
+    print gfx('first line', fgcol='red', opts=('noreset',))
+    print 'this should be red too'
+    print gfx('and so should this')
+    print 'this should not be red'
+"""
+    text = str(text)
+    if DISABLE:
+        return text
+    code_list = []
+    if text == '' and len(opts) == 1 and opts[0] == 'reset':
+        return '\x1b[%sm' % RESET
+    for k,v in kwargs.iteritems():
+        if k == 'fgcol':
+            code_list.append(foreground[v])
+        elif k == 'bgcol':
+            code_list.append(background[v])
+    for o in opts:
+        if o in opt_dict:
+            code_list.append(opt_dict[o])
+    if not ('noreset' in opts):
+        text = text + '\x1b[%sm' % RESET
+    return ('\x1b[%sm' % ';'.join(code_list)) + text
+
+def make_style(opts=(), **kwargs):
+    """Returns a function with default parameters for gfx()
+
+    Example:
+        bold_red = make_style(opts=('bold',), fgcol='red')
+        print bold_red('hello')
+
+        KEYWORD = make_style(fgcol='yellow')
+        COMMENT = make_style(fgcol='blue', opts=('bold',))
+    etc
+    """
+    return lambda text: gfx(text, opts, **kwargs)
+
+    result = ''
+    for a in args:
+        if a.__class__ in types.StringTypes:
+            result += a
+        elif a.__class__ in [types.TupleType, types.ListType]:
+            result += a[0](a[1])
+    return result
+
Index: management.py
===================================================================
--- management.py	(revision 2509)
+++ management.py	(working copy)
@@ -4,7 +4,38 @@
 import django
 import os, re, sys, textwrap
 from optparse import OptionParser
+import termcolors
 
+class dummy:
+    pass
+
+style = dummy()
+
+style.ERROR = termcolors.make_style(fgcol='white', bgcol='red', opts=('bold',))
+style.ERROR_OUTPUT = termcolors.make_style(fgcol='red', opts=('bold',))
+style.OK = termcolors.make_style(fgcol='green', opts=('bold',))
+style.SQL_STRING = termcolors.make_style(fgcol='cyan')
+style.SQL_FIELD = termcolors.make_style(fgcol='green')
+style.SQL_KEYWORD = termcolors.make_style(fgcol='yellow')
+style.SQL_NUMBER = style.SQL_STRING
+style.SQL_TABLE = termcolors.make_style(fgcol='green', opts=('bold',))
+style.SQL_TRANS = termcolors.make_style(opts=('bold',))
+
+def J(*args):
+    return ''.join(map(str, args))
+
+def disable_sql_styles():
+    l = lambda x: x
+    style.SQL_STRING = l
+    style.SQL_FIELD = l
+    style.SQL_KEYWORD = l
+    style.SQL_TABLE = l
+
+if (not sys.stdout.isatty()) or (sys.platform == 'win32'):
+    # if somebody's piping our output through to psql or something,
+    # they might be a touch miffed if it's all full of escape chars
+    termcolors.DISABLE = True
+
 # For Python 2.3
 if not hasattr(__builtins__, 'set'):
     from sets import Set as set
@@ -27,9 +58,13 @@
 
 def _get_packages_insert(app_label):
     from django.core.db import db
-    return "INSERT INTO %s (%s, %s) VALUES ('%s', '%s');" % \
-        (db.quote_name('packages'), db.quote_name('label'), db.quote_name('name'),
-        app_label, app_label)
+    return J(style.SQL_KEYWORD("INSERT INTO")," %s (%s, %s) ",
+                   style.SQL_KEYWORD("VALUES")," (%s, %s);") % \
+        (style.SQL_TABLE(db.quote_name('packages')),
+         style.SQL_FIELD(db.quote_name('label')),
+         style.SQL_FIELD(db.quote_name('name')),
+         style.SQL_STRING("'"+app_label+"'"),
+         style.SQL_STRING("'"+app_label+"'"))
 
 def _get_permission_codename(action, opts):
     return '%s_%s' % (action, opts.object_name.lower())
@@ -44,15 +79,27 @@
 
 def _get_permission_insert(name, codename, opts):
     from django.core.db import db
-    return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \
-        (db.quote_name('auth_permissions'), db.quote_name('name'), db.quote_name('package'),
-        db.quote_name('codename'), name.replace("'", "''"), opts.app_label, codename)
+    return J(style.SQL_KEYWORD("INSERT INTO")," %s (%s, %s, %s) ",
+                   style.SQL_KEYWORD("VALUES")," (%s, %s, %s);") % \
+        (style.SQL_TABLE(db.quote_name('auth_permissions')),
+         style.SQL_FIELD(db.quote_name('name')),
+         style.SQL_FIELD(db.quote_name('package')),
+         style.SQL_FIELD(db.quote_name('codename')),
+         style.SQL_STRING("'"+name.replace("'", "''")+"'"),
+         style.SQL_STRING("'"+opts.app_label+"'"),
+         style.SQL_STRING("'"+codename+"'"))
 
 def _get_contenttype_insert(opts):
     from django.core.db import db
-    return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \
-        (db.quote_name('content_types'), db.quote_name('name'), db.quote_name('package'),
-        db.quote_name('python_module_name'), opts.verbose_name, opts.app_label, opts.module_name)
+    return J(style.SQL_KEYWORD("INSERT INTO"), " %s (%s, %s, %s) ",
+                   style.SQL_KEYWORD("VALUES"), " (%s, %s, %s);") % \
+        (style.SQL_TABLE(db.quote_name('content_types')),
+         style.SQL_FIELD(db.quote_name('name')),
+         style.SQL_FIELD(db.quote_name('package')),
+         style.SQL_FIELD(db.quote_name('python_module_name')),
+         style.SQL_STRING("'"+opts.verbose_name.__str__()+"'"),
+         style.SQL_STRING("'"+opts.app_label.__str__()+"'"),
+         style.SQL_STRING("'"+opts.module_name.__str__()+"'"))
 
 def _is_valid_dir_name(s):
     return bool(re.search(r'^\w+$', s))
@@ -87,24 +134,29 @@
                 data_type = f.get_internal_type()
             col_type = db.DATA_TYPES[data_type]
             if col_type is not None:
-                field_output = [db.db.quote_name(f.column), col_type % rel_field.__dict__]
-                field_output.append('%sNULL' % (not f.null and 'NOT ' or ''))
+                field_output = [style.SQL_FIELD(db.db.quote_name(f.column)),
+                                col_type % rel_field.__dict__]
+                field_output.append(style.SQL_KEYWORD('%sNULL') % \
+                        (not f.null and 'NOT ' or ''))
                 if f.unique:
-                    field_output.append('UNIQUE')
+                    field_output.append(style.SQL_KEYWORD('UNIQUE'))
                 if f.primary_key:
-                    field_output.append('PRIMARY KEY')
+                    field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
                 if f.rel:
-                    field_output.append('REFERENCES %s (%s)' % \
-                        (db.db.quote_name(f.rel.to.db_table),
-                        db.db.quote_name(f.rel.to.get_field(f.rel.field_name).column)))
+                    field_output.append(J(style.SQL_KEYWORD('REFERENCES'),
+                                        ' %s (%s)') % \
+                        (style.SQL_TABLE(db.db.quote_name(f.rel.to.db_table)),
+                        style.SQL_FIELD(db.db.quote_name(f.rel.to.get_field(f.rel.field_name).column))))
                 table_output.append(' '.join(field_output))
         if opts.order_with_respect_to:
-            table_output.append('%s %s NULL' % (db.db.quote_name('_order'), db.DATA_TYPES['IntegerField']))
+            table_output.append(J('%s %s ',style.SQL_KEYWORD('NULL')) % \
+                    (style.SQL_FIELD(db.db.quote_name('_order')),
+                        db.DATA_TYPES['IntegerField']))
         for field_constraints in opts.unique_together:
-            table_output.append('UNIQUE (%s)' % \
-                ", ".join([db.db.quote_name(opts.get_field(f).column) for f in field_constraints]))
+            table_output.append(style.SQL_KEYWORD('UNIQUE')+' (%s)' % \
+                ", ".join([style.SQL_FIELD(db.db.quote_name(opts.get_field(f).column)) for f in field_constraints]))
 
-        full_statement = ['CREATE TABLE %s (' % db.db.quote_name(opts.db_table)]
+        full_statement = [style.SQL_KEYWORD('CREATE TABLE')+' %s (' % style.SQL_TABLE(db.db.quote_name(opts.db_table))]
         for i, line in enumerate(table_output): # Combine and add commas.
             full_statement.append('    %s%s' % (line, i < len(table_output)-1 and ',' or ''))
         full_statement.append(');')
@@ -113,21 +165,29 @@
     for klass in mod._MODELS:
         opts = klass._meta
         for f in opts.many_to_many:
-            table_output = ['CREATE TABLE %s (' % db.db.quote_name(f.get_m2m_db_table(opts))]
-            table_output.append('    %s %s NOT NULL PRIMARY KEY,' % (db.db.quote_name('id'), db.DATA_TYPES['AutoField']))
-            table_output.append('    %s %s NOT NULL REFERENCES %s (%s),' % \
-                (db.db.quote_name(opts.object_name.lower() + '_id'),
+            table_output = [J(style.SQL_KEYWORD('CREATE TABLE'),' %s (') % \
+                    style.SQL_TABLE(db.db.quote_name(f.get_m2m_db_table(opts))
+                            )]
+            table_output.append(J('    %s %s ',
+                style.SQL_KEYWORD('NOT NULL PRIMARY KEY'),',') % \
+                        (style.SQL_FIELD(db.db.quote_name('id')),
+                            db.DATA_TYPES['AutoField']))
+            table_output.append(J('    %s %s ',
+                style.SQL_KEYWORD('NOT NULL REFERENCES'),' %s (%s),') % \
+                (style.SQL_FIELD(db.db.quote_name(opts.object_name.lower() + '_id')),
                 db.DATA_TYPES[get_rel_data_type(opts.pk)] % opts.pk.__dict__,
-                db.db.quote_name(opts.db_table),
-                db.db.quote_name(opts.pk.column)))
-            table_output.append('    %s %s NOT NULL REFERENCES %s (%s),' % \
-                (db.db.quote_name(f.rel.to.object_name.lower() + '_id'),
+                style.SQL_TABLE(db.db.quote_name(opts.db_table)),
+                style.SQL_FIELD(db.db.quote_name(opts.pk.column))))
+            table_output.append(J('    %s %s ',
+                style.SQL_KEYWORD('NOT NULL REFERENCES'),' %s (%s),') % \
+                (style.SQL_FIELD(db.db.quote_name(f.rel.to.object_name.lower() + '_id')),
                 db.DATA_TYPES[get_rel_data_type(f.rel.to.pk)] % f.rel.to.pk.__dict__,
-                db.db.quote_name(f.rel.to.db_table),
-                db.db.quote_name(f.rel.to.pk.column)))
-            table_output.append('    UNIQUE (%s, %s)' % \
-                (db.db.quote_name(opts.object_name.lower() + '_id'),
-                db.db.quote_name(f.rel.to.object_name.lower() + '_id')))
+                style.SQL_TABLE(db.db.quote_name(f.rel.to.db_table)),
+                style.SQL_FIELD(db.db.quote_name(f.rel.to.pk.column))))
+            table_output.append(J('    ',style.SQL_KEYWORD('UNIQUE'),
+                ' (%s, %s)') % \
+                (style.SQL_FIELD(db.db.quote_name(opts.object_name.lower() + '_id')),
+                style.SQL_FIELD(db.db.quote_name(f.rel.to.object_name.lower() + '_id'))))
             table_output.append(');')
             final_output.append('\n'.join(table_output))
     return final_output
@@ -167,7 +227,8 @@
             # The table doesn't exist, so it doesn't need to be dropped.
             db.db.rollback()
         else:
-            output.append("DROP TABLE %s;" % db.db.quote_name(klass._meta.db_table))
+            output.append(J(style.SQL_KEYWORD("DROP TABLE")," %s;") % \
+                    style.SQL_TABLE(db.db.quote_name(klass._meta.db_table)))
 
     # Output DROP TABLE statements for many-to-many tables.
     for klass in mod._MODELS:
@@ -175,21 +236,32 @@
         for f in opts.many_to_many:
             try:
                 if cursor is not None:
-                    cursor.execute("SELECT 1 FROM %s LIMIT 1" % db.db.quote_name(f.get_m2m_db_table(opts)))
+                    cursor.execute("SELECT 1 FROM %s LIMIT 1" % \
+                            db.db.quote_name(f.get_m2m_db_table(opts)))
             except:
                 db.db.rollback()
             else:
-                output.append("DROP TABLE %s;" % db.db.quote_name(f.get_m2m_db_table(opts)))
+                output.append(J(style.SQL_KEYWORD("DROP TABLE")," %s;") % \
+                        style.SQL_TABLE(db.db.quote_name(f.get_m2m_db_table(opts))))
 
     app_label = mod._MODELS[0]._meta.app_label
 
     # Delete from packages, auth_permissions, content_types.
-    output.append("DELETE FROM %s WHERE %s = '%s';" % \
-        (db.db.quote_name('packages'), db.db.quote_name('label'), app_label))
-    output.append("DELETE FROM %s WHERE %s = '%s';" % \
-        (db.db.quote_name('auth_permissions'), db.db.quote_name('package'), app_label))
-    output.append("DELETE FROM %s WHERE %s = '%s';" % \
-        (db.db.quote_name('content_types'), db.db.quote_name('package'), app_label))
+    output.append(J(style.SQL_KEYWORD("DELETE FROM")," %s ",
+        style.SQL_KEYWORD("WHERE")," %s = %s;") % \
+        (style.SQL_TABLE(db.db.quote_name('packages')),
+            style.SQL_FIELD(db.db.quote_name('label')),
+            style.SQL_STRING("'"+app_label+"'")))
+    output.append(J(style.SQL_KEYWORD("DELETE FROM")," %s ",
+        style.SQL_KEYWORD("WHERE")," %s = %s;") % \
+        (style.SQL_TABLE(db.db.quote_name('auth_permissions')),
+            style.SQL_FIELD(db.db.quote_name('package')),
+            style.SQL_STRING("'"+app_label+"'")))
+    output.append(J(style.SQL_KEYWORD("DELETE FROM")," %s ",
+        style.SQL_KEYWORD("WHERE")," %s = %s;") % \
+        (style.SQL_TABLE(db.db.quote_name('content_types')),
+            style.SQL_FIELD(db.db.quote_name('package')),
+            style.SQL_STRING("'"+app_label+"'")))
 
     # Delete from the admin log.
     if cursor is not None:
@@ -198,8 +270,11 @@
             db.db.quote_name('package')), [app_label])
         if admin_log_exists:
             for row in cursor.fetchall():
-                output.append("DELETE FROM %s WHERE %s = %s;" % \
-                    (db.db.quote_name('django_admin_log'), db.db.quote_name('content_type_id'), row[0]))
+                output.append(J(style.SQL_KEYWORD("DELETE FROM")," %s ",
+                    style.SQL_KEYWORD("WHERE")," %s = %s;") % \
+                    (style.SQL_TABLE(db.db.quote_name('django_admin_log')),
+                        style.SQL_FIELD(db.db.quote_name('content_type_id')),
+                        style.SQL_NUMBER(row[0])))
 
     # Close database connection explicitly, in case this output is being piped
     # directly into a database client, to avoid locking issues.
@@ -252,12 +327,22 @@
     for klass in mod._MODELS:
         for f in klass._meta.fields:
             if isinstance(f, meta.AutoField):
-                output.append("SELECT setval('%s_%s_seq', (SELECT max(%s) FROM %s));" % \
-                    (klass._meta.db_table, f.column, db.db.quote_name(f.column),
-                    db.db.quote_name(klass._meta.db_table)))
+                output.append(J(style.SQL_KEYWORD("SELECT"),
+                    " setval('%s_%s_seq', (",
+                    style.SQL_KEYWORD("SELECT")," max(%s) ",
+                    style.SQL_KEYWORD("FROM")," %s));") % \
+                    (klass._meta.db_table,
+                        f.column,
+                        style.SQL_FIELD(db.db.quote_name(f.column)),
+                    style.SQL_TABLE(db.db.quote_name(klass._meta.db_table))))
         for f in klass._meta.many_to_many:
-            output.append("SELECT setval('%s_id_seq', (SELECT max(%s) FROM %s));" % \
-                (f.get_m2m_db_table(klass._meta), db.db.quote_name('id'), f.get_m2m_db_table(klass._meta)))
+            output.append(J(style.SQL_KEYWORD("SELECT"),
+                " setval('%s_id_seq', (",
+                style.SQL_KEYWORD("SELECT")," max(%s) ",
+                style.SQL_KEYWORD("FROM")," %s));") % \
+                (f.get_m2m_db_table(klass._meta),
+                    style.SQL_FIELD(db.db.quote_name('id')),
+                    style.SQL_TABLE(f.get_m2m_db_table(klass._meta))))
     return output
 get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given model module name(s)."
 get_sql_sequence_reset.args = APP_ARGS
@@ -270,9 +355,10 @@
         for f in klass._meta.fields:
             if f.db_index:
                 unique = f.unique and "UNIQUE " or ""
-                output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \
+                output.append(J(style.SQL_KEYWORD("CREATE %sINDEX")," %s_%s ",style.SQL_KEYWORD("ON")," %s (%s);") % \
                     (unique, klass._meta.db_table, f.column,
-                    db.quote_name(klass._meta.db_table), db.quote_name(f.column)))
+                    style.SQL_TABLE(db.quote_name(klass._meta.db_table)),
+                    style.SQL_FIELD(db.quote_name(f.column))))
     return output
 get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
 get_sql_indexes.args = APP_ARGS
@@ -337,9 +423,14 @@
             perms_seen[row[0]]
         except KeyError:
 #             sys.stderr.write("A permission called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0]))
-            print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \
-                (db.db.quote_name('auth_permissions'), db.db.quote_name('package'),
-                app_label, db.db.quote_name('codename'), row[0])
+            print J(style.SQL_KEYWORD("DELETE FROM"), " %s ",
+                    style.SQL_KEYWORD("WHERE"), " %s='%s' ",
+                    style.SQL_KEYWORD("AND"), " %s = '%s';") % \
+                (style.SQL_TABLE(db.db.quote_name('auth_permissions')),
+                        style.SQL_FIELD(db.db.quote_name('package')),
+                        style.SQL_STRING(app_label),
+                        style.SQL_FIELD(db.db.quote_name('codename')),
+                        style.SQL_STRING(row[0]))
 
     # Check that there aren't any *extra* content types in the DB that the
     # model doesn't know about.
@@ -351,9 +442,14 @@
             contenttypes_seen[row[0]]
         except KeyError:
 #             sys.stderr.write("A content type called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0]))
-            print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \
-                (db.db.quote_name('content_types'), db.db.quote_name('package'),
-                app_label, db.db.quote_name('python_module_name'), row[0])
+            print J(style.SQL_KEYWORD("DELETE FROM")," %s ",
+                    style.SQL_KEYWORD("WHERE")," %s='%s' ",
+                    style.SQL_KEYWORD("AND")," %s = '%s';") % \
+                (style.SQL_TABLE(db.db.quote_name('content_types')),
+                        style.SQL_FIELD(db.db.quote_name('package')),
+                        style.SQL_STRING(app_label),
+                        style.SQL_FIELD(db.db.quote_name('python_module_name')),
+                        style.SQL_STRING(row[0]))
 database_check.help_doc = "Checks that everything is installed in the database for the given model module name(s) and prints SQL statements if needed."
 database_check.args = APP_ARGS
 
@@ -381,6 +477,7 @@
 
 def init():
     "Initializes the database with auth and core."
+    disable_sql_styles()
     try:
         from django.core import db, meta
         auth = meta.get_app('auth')
@@ -392,7 +489,10 @@
             (db.db.quote_name(core.Site._meta.db_table), db.db.quote_name('domain'),
             db.db.quote_name('name')))
     except Exception, e:
-        sys.stderr.write("Error: The database couldn't be initialized.\n%s\n" % e)
+        sys.stderr.write(
+                J(style.ERROR("Error: The database couldn't be initialized."),
+                    "\n",style.ERROR_OUTPUT(e),"\n")
+                    )
         try:
             db.db.rollback()
         except UnboundLocalError:
@@ -408,13 +508,14 @@
     from cStringIO import StringIO
     mod_name = mod.__name__[mod.__name__.rindex('.')+1:]
 
+    disable_sql_styles()
     # First, try validating the models.
     s = StringIO()
     num_errors = get_validation_errors(s)
     if num_errors:
-        sys.stderr.write("Error: %s couldn't be installed, because there were errors in your model:\n" % mod_name)
+        sys.stderr.write(J(style.ERROR("Error: %s couldn't be installed, because there were errors in your model:"),"\n") % mod_name)
         s.seek(0)
-        sys.stderr.write(s.read())
+        sys.stderr.write(style.ERROR_OUTPUT(s.read()))
         sys.exit(1)
     sql_list = get_sql_all(mod)
 
@@ -423,12 +524,14 @@
         for sql in sql_list:
             cursor.execute(sql)
     except Exception, e:
-        sys.stderr.write("""Error: %s couldn't be installed. Possible reasons:
+        sys.stderr.write(
+        J(style.ERROR("Error: %s couldn't be installed. Possible reasons:"),
+        style.ERROR_OUTPUT("""
   * The database isn't running or isn't configured correctly.
   * At least one of the database tables already exists.
   * The SQL was invalid.
 Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this command wasn't able to run.
-The full error: %s\n""" % \
+The full error: %s"""),"\n") % \
             (mod_name, mod_name, e))
         db.db.rollback()
         sys.exit(1)
@@ -440,6 +543,9 @@
     "Installs any permissions for the given model, if needed."
     from django.models.auth import permissions
     from django.models.core import packages
+
+    disable_sql_styles()
+    
     num_added = 0
     package = packages.get_object(pk=mod._MODELS[0]._meta.app_label)
     for klass in mod._MODELS:
@@ -450,23 +556,23 @@
             except permissions.PermissionDoesNotExist:
                 p = permissions.Permission(name=name, package=package, codename=codename)
                 p.save()
-                print "Added permission '%r'." % p
+                print style.OK("Added permission '%r'." % p)
                 num_added += 1
     if not num_added:
-        print "No permissions were added, because all necessary permissions were already installed."
+        print style.OK("No permissions were added, because all necessary permissions were already installed.")
 installperms.help_doc = "Installs any permissions for the given model module name(s), if needed."
 installperms.args = APP_ARGS
 
 def _start_helper(app_or_project, name, directory, other_name=''):
     other = {'project': 'app', 'app': 'project'}[app_or_project]
     if not _is_valid_dir_name(name):
-        sys.stderr.write("Error: %r is not a valid %s name. Please use only numbers, letters and underscores.\n" % (name, app_or_project))
+        sys.stderr.write(J(style.ERROR("Error: %r is not a valid %s name. Please use only numbers, letters and underscores."),"\n") % (name, app_or_project))
         sys.exit(1)
     top_dir = os.path.join(directory, name)
     try:
         os.mkdir(top_dir)
     except OSError, e:
-        sys.stderr.write("Error: %s\n" % e)
+        sys.stderr.write(J(style.ERROR("Error: %s"),"\n") % e)
         sys.exit(1)
     template_dir = PROJECT_TEMPLATE_DIR % app_or_project
     for d, subdirs, files in os.walk(template_dir):
@@ -489,14 +595,14 @@
     "Creates a Django project for the given project_name in the given directory."
     from random import choice
     if project_name in INVALID_PROJECT_NAMES:
-        sys.stderr.write("Error: %r isn't a valid project name. Please try another.\n" % project_name)
+        sys.stderr.write(J(style.ERROR("Error: %r isn't a valid project name. Please try another."),"\n") % project_name)
         sys.exit(1)
     _start_helper('project', project_name, directory)
     # Create a random SECRET_KEY hash, and put it in the main settings.
     main_settings_file = os.path.join(directory, project_name, 'settings.py')
     settings_contents = open(main_settings_file, 'r').read()
     fp = open(main_settings_file, 'w')
-    secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
+    secret_key = J([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
     settings_contents = re.sub(r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents)
     fp.write(settings_contents)
     fp.close()
@@ -523,14 +629,14 @@
             if not username:
                 username = raw_input('Username (only letters, digits and underscores): ')
             if not username.isalnum():
-                sys.stderr.write("Error: That username is invalid.\n")
+                sys.stderr.write(J(style.ERROR("Error: That username is invalid."),"\n"))
                 username = None
             try:
                 users.get_object(username__exact=username)
             except users.UserDoesNotExist:
                 break
             else:
-                sys.stderr.write("Error: That username is already taken.\n")
+                sys.stderr.write(J(style.ERROR("Error: That username is already taken."),"\n"))
                 username = None
         while 1:
             if not email:
@@ -538,7 +644,7 @@
             try:
                 validators.isValidEmail(email, None)
             except validators.ValidationError:
-                sys.stderr.write("Error: That e-mail address is invalid.\n")
+                sys.stderr.write(J(style.ERROR("Error: That e-mail address is invalid."),"\n"))
                 email = None
             else:
                 break
@@ -547,23 +653,23 @@
                 password = getpass.getpass()
                 password2 = getpass.getpass('Password (again): ')
                 if password != password2:
-                    sys.stderr.write("Error: Your passwords didn't match.\n")
+                    sys.stderr.write(J(style.ERROR("Error: Your passwords didn't match."),"\n"))
                     password = None
                     continue
             if password.strip() == '':
-                sys.stderr.write("Error: Blank passwords aren't allowed.\n")
+                sys.stderr.write(J(style.ERROR("Error: Blank passwords aren't allowed."),"\n"))
                 password = None
                 continue
             break
     except KeyboardInterrupt:
-        sys.stderr.write("\nOperation cancelled.\n")
+        sys.stderr.write(J('\n',style.ERROR("Operation cancelled."),'\n'))
         sys.exit(1)
     u = users.create_user(username, email, password)
     u.is_staff = True
     u.is_active = True
     u.is_superuser = True
     u.save()
-    print "User created successfully."
+    print style.OK("User created successfully.")
 createsuperuser.args = '[username] [email] [password] (Either all or none)'
 
 def inspectdb(db_name):
@@ -798,14 +904,15 @@
     if not addr:
         addr = '127.0.0.1'
     if not port.isdigit():
-        sys.stderr.write("Error: %r is not a valid port number.\n" % port)
+        sys.stderr.write(style.ERROR("Error: %r is not a valid port number.\n" % port))
         sys.exit(1)
     def inner_run():
         from django.conf.settings import SETTINGS_MODULE
         print "Validating models..."
         validate()
-        print "\nDjango version %s, using settings %r" % (get_version(), SETTINGS_MODULE)
-        print "Development server is running at http://%s:%s/" % (addr, port)
+        print
+        print style.OK("Django version %s, using settings %r") % (get_version(), SETTINGS_MODULE)
+        print style.OK("Development server is running at http://%s:%s/" % (addr, port))
         print "Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows)."
         try:
             run(addr, int(port), AdminMediaHandler(WSGIHandler()))
@@ -820,7 +927,7 @@
                 error_text = ERRORS[e.args[0].args[0]]
             except (AttributeError, KeyError):
                 error_text = str(e)
-            sys.stderr.write("Error: %s\n" % error_text)
+            sys.stderr.write(style.ERROR("Error: %s\n" % error_text))
             sys.exit(1)
         except KeyboardInterrupt:
             sys.exit(0)
@@ -925,7 +1032,7 @@
     return '\n'.join(usage[:-1]) # Cut off last list element, an empty space.
 
 def print_error(msg, cmd):
-    sys.stderr.write('Error: %s\nRun "%s --help" for help.\n' % (msg, cmd))
+    sys.stderr.write(J(style.ERROR('Error: %s'),'\n',style.ERROR_OUTPUT('Run "%s --help" for help.'),'\n') % (msg, cmd))
     sys.exit(1)
 
 def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
@@ -968,7 +1075,7 @@
             if len(args) == 1: # We got no arguments, just the action.
                 action_mapping[action]()
             else:
-                sys.stderr.write("Error: %r requires arguments of 'username email password' or no argument at all.\n")
+                sys.stderr.write(J(style.ERROR("Error: %r requires arguments of 'username email password' or no argument at all."),"\n"))
                 sys.exit(1)
         else:
             action_mapping[action](username, email, password)
@@ -985,7 +1092,7 @@
             for line in action_mapping[action](param):
                 print line
         except NotImplementedError:
-            sys.stderr.write("Error: %r isn't supported for the currently selected database backend.\n" % action)
+            sys.stderr.write(J(style.ERROR("Error: %r isn't supported for the currently selected database backend."),"\n") % action)
             sys.exit(1)
     elif action == 'createcachetable':
         try:
@@ -1016,18 +1123,18 @@
             try:
                 mod_list = [meta.get_app(app_label) for app_label in args[1:]]
             except ImportError, e:
-                sys.stderr.write("Error: %s. Are you sure your INSTALLED_APPS setting is correct?\n" % e)
+                sys.stderr.write(J(style.ERROR("Error: %s. Are you sure your INSTALLED_APPS setting is correct?"),"\n") % e)
                 sys.exit(1)
             if not mod_list:
                 parser.print_usage_and_exit()
         if action not in NO_SQL_TRANSACTION:
-            print "BEGIN;"
+            print J(style.SQL_TRANS("BEGIN"), ';')
         for mod in mod_list:
             output = action_mapping[action](mod)
             if output:
                 print '\n'.join(output)
         if action not in NO_SQL_TRANSACTION:
-            print "COMMIT;"
+            print J(style.SQL_TRANS("COMMIT"),';')
 
 def execute_manager(settings_mod):
     # Add this project to sys.path so that it's importable in the conventional
