Commits

Anonymous committed 348208c

Refs #2333 - Added 'test' target to django-admin script. Includes addition of --verbosity and --noinput options to django-admin, and a new TEST_RUNNER setting to control the tool used to execute tests.

Comments (0)

Files changed (5)

django/conf/global_settings.py

 ##################
 
 AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
+
+###########
+# TESTING #
+###########
+
+TEST_RUNNER='django.test.simple.run_tests'

django/contrib/auth/management.py

         perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name)))
     return perms + list(opts.permissions)
 
-def create_permissions(app, created_models):
+def create_permissions(app, created_models, verbosity):
     from django.contrib.contenttypes.models import ContentType
     from django.contrib.auth.models import Permission
     app_models = get_models(app)
         for codename, name in _get_all_permissions(klass._meta):
             p, created = Permission.objects.get_or_create(codename=codename, content_type__pk=ctype.id,
                 defaults={'name': name, 'content_type': ctype})
-            if created:
+            if created and verbosity >= 2:
                 print "Adding permission '%s'" % p
 
-def create_superuser(app, created_models):
+def create_superuser(app, created_models, verbosity, **kwargs):
     from django.contrib.auth.models import User
     from django.contrib.auth.create_superuser import createsuperuser as do_create
-    if User in created_models:
+    if User in created_models and kwargs.get('interactive', True):
         msg = "\nYou just installed Django's auth system, which means you don't have " \
                 "any superusers defined.\nWould you like to create one now? (yes/no): "
         confirm = raw_input(msg)

django/contrib/contenttypes/management.py

 from django.dispatch import dispatcher
 from django.db.models import get_models, signals
 
-def create_contenttypes(app, created_models):
+def create_contenttypes(app, created_models, verbosity):
     from django.contrib.contenttypes.models import ContentType
     app_models = get_models(app)
     if not app_models:
             ct = ContentType(name=str(opts.verbose_name),
                 app_label=opts.app_label, model=opts.object_name.lower())
             ct.save()
-            print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
+            if verbosity >= 2:
+                print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
 
 dispatcher.connect(create_contenttypes, signal=signals.post_syncdb)

django/contrib/sites/management.py

 from django.contrib.sites.models import Site
 from django.contrib.sites import models as site_app
 
-def create_default_site(app, created_models):
+def create_default_site(app, created_models, verbosity):
     if Site in created_models:
-        print "Creating example.com Site object"
+        if verbosity >= 2:
+            print "Creating example.com Site object"
         s = Site(domain="example.com", name="example.com")
         s.save()
 

django/core/management.py

 get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
 get_sql_all.args = APP_ARGS
 
-def syncdb():
+def syncdb(verbosity=2, interactive=True):
     "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
     from django.db import connection, transaction, models, get_creation_module
     from django.db.models import signals
                 except KeyError:
                     pending_references[refto] = refs
             sql.extend(_get_sql_for_pending_references(model, pending_references))
-            print "Creating table %s" % model._meta.db_table
+            if verbosity >= 2:
+                print "Creating table %s" % model._meta.db_table
             for statement in sql:
                 cursor.execute(statement)
             table_list.append(model._meta.db_table)
             if model in created_models:
                 sql = _get_many_to_many_sql_for_model(model)
                 if sql:
-                    print "Creating many-to-many tables for %s model" % model.__name__
+                    if verbosity >= 2:
+                        print "Creating many-to-many tables for %s model" % model.__name__
                     for statement in sql:
                         cursor.execute(statement)
 
     # to do at this point.
     for app in models.get_apps():
         dispatcher.send(signal=signals.post_syncdb, sender=app,
-            app=app, created_models=created_models)
+            app=app, created_models=created_models, 
+            verbosity=verbosity, interactive=interactive)
 
         # Install initial data for the app (but only if this is a model we've
         # just created)
     runfastcgi(args)
 runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
 
+def test(verbosity, app_labels):
+    "Runs the test suite for the specified applications"
+    from django.conf import settings
+    from django.db.models import get_app, get_apps
+
+    if len(app_labels) == 0:
+        app_list = get_apps()
+    else:
+        app_list = [get_app(app_label) for app_label in app_labels]
+    
+    test_path = settings.TEST_RUNNER.split('.')
+    # Allow for Python 2.5 relative paths
+    if len(test_path) > 1:
+        test_module_name = '.'.join(test_path[:-1])
+    else:
+        test_module_name = '.'
+    test_module = __import__(test_module_name, [],[],test_path[-1])
+    test_runner = getattr(test_module, test_path[-1])
+    
+    test_runner(app_list, verbosity)
+test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
+test.args = '[--verbosity] ' + APP_ARGS
+
 # Utilities for command-line script
 
 DEFAULT_ACTION_MAPPING = {
     'startproject': startproject,
     'syncdb': syncdb,
     'validate': validate,
+    'test':test,
 }
 
 NO_SQL_TRANSACTION = (
         help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
     parser.add_option('--plain', action='store_true', dest='plain',
         help='Tells Django to use plain Python, not IPython, for "shell" command.')
+    parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
+        help='Tells Django to NOT prompt the user for input of any kind.')
     parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
         help='Tells Django to NOT use the auto-reloader when running the development server.')
+    parser.add_option('--verbosity', action='store', dest='verbosity', default='2',
+        type='choice', choices=['0', '1', '2'],
+        help='Verbosity level; 0=minimal output, 1=normal output, 2=all output')
+
     options, args = parser.parse_args(argv[1:])
 
     # Take care of options.
 
     if action == 'shell':
         action_mapping[action](options.plain is True)
-    elif action in ('syncdb', 'validate', 'diffsettings', 'dbshell'):
+    elif action in ('validate', 'diffsettings', 'dbshell'):
         action_mapping[action]()
+    elif action == 'syncdb':
+        action_mapping[action](int(options.verbosity), options.interactive)
     elif action == 'inspectdb':
         try:
             for line in action_mapping[action]():
             action_mapping[action](args[1])
         except IndexError:
             parser.print_usage_and_exit()
+    elif action == 'test':
+        try:
+            action_mapping[action](int(options.verbosity), args[1:])
+        except IndexError:
+            parser.print_usage_and_exit()
     elif action in ('startapp', 'startproject'):
         try:
             name = args[1]