From 77ab11be452d2da50925d5d2e3eed1b96ba7eca0 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 27 Aug 2006 12:46:39 +0000 Subject: [PATCH] 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. git-svn-id: http://code.djangoproject.com/svn/django/trunk@3660 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/conf/global_settings.py | 6 +++ django/contrib/auth/management.py | 8 ++-- django/contrib/contenttypes/management.py | 5 ++- django/contrib/sites/management.py | 5 ++- django/core/management.py | 50 ++++++++++++++++++++--- 5 files changed, 61 insertions(+), 13 deletions(-) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 4ea694d064..56a4ccb48a 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -296,3 +296,9 @@ BANNED_IPS = () ################## AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) + +########### +# TESTING # +########### + +TEST_RUNNER='django.test.simple.run_tests' diff --git a/django/contrib/auth/management.py b/django/contrib/auth/management.py index 1a07417f1d..3f52681747 100644 --- a/django/contrib/auth/management.py +++ b/django/contrib/auth/management.py @@ -16,7 +16,7 @@ def _get_all_permissions(opts): 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) @@ -27,13 +27,13 @@ def create_permissions(app, created_models): 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) diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py index a9174584bc..de3a685477 100644 --- a/django/contrib/contenttypes/management.py +++ b/django/contrib/contenttypes/management.py @@ -5,7 +5,7 @@ Creates content types for all installed models. 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: @@ -19,6 +19,7 @@ def create_contenttypes(app, created_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) diff --git a/django/contrib/sites/management.py b/django/contrib/sites/management.py index 0e1a50227a..6831cab96d 100644 --- a/django/contrib/sites/management.py +++ b/django/contrib/sites/management.py @@ -7,9 +7,10 @@ from django.db.models import signals 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() diff --git a/django/core/management.py b/django/core/management.py index a469c72901..51c8c760d5 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -423,7 +423,7 @@ def get_sql_all(app): 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 @@ -471,7 +471,8 @@ def syncdb(): 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) @@ -480,7 +481,8 @@ def syncdb(): 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) @@ -490,7 +492,8 @@ def syncdb(): # 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) @@ -1154,6 +1157,29 @@ def runfcgi(args): 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 = { @@ -1178,6 +1204,7 @@ DEFAULT_ACTION_MAPPING = { 'startproject': startproject, 'syncdb': syncdb, 'validate': validate, + 'test':test, } NO_SQL_TRANSACTION = ( @@ -1228,8 +1255,14 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): 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. @@ -1256,8 +1289,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): 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](): @@ -1270,6 +1305,11 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): 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]