From 6d210ef40341b26aa2881fbb82ef7a7cdd54a3df Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Tue, 6 Dec 2005 05:17:52 +0000 Subject: [PATCH] Moved all logic from django-admin.py into django.core.management, into a new execute_from_command_line() function, so it can be called from other scripts. Also improved createproject to disallow 'django' and 'test' as project names. git-svn-id: http://code.djangoproject.com/svn/django/trunk@1553 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/bin/django-admin.py | 150 +---------------------------------- django/core/management.py | 155 ++++++++++++++++++++++++++++++++++++- 2 files changed, 155 insertions(+), 150 deletions(-) diff --git a/django/bin/django-admin.py b/django/bin/django-admin.py index 63c6307257..f518cdc463 100755 --- a/django/bin/django-admin.py +++ b/django/bin/django-admin.py @@ -1,153 +1,5 @@ #!/usr/bin/env python from django.core import management -from optparse import OptionParser -import os, sys, textwrap - -ACTION_MAPPING = { - 'adminindex': management.get_admin_index, - 'createsuperuser': management.createsuperuser, - 'createcachetable' : management.createcachetable, -# 'dbcheck': management.database_check, - 'init': management.init, - 'inspectdb': management.inspectdb, - 'install': management.install, - 'installperms': management.installperms, - 'runserver': management.runserver, - 'sql': management.get_sql_create, - 'sqlall': management.get_sql_all, - 'sqlclear': management.get_sql_delete, - 'sqlindexes': management.get_sql_indexes, - 'sqlinitialdata': management.get_sql_initial_data, - 'sqlreset': management.get_sql_reset, - 'sqlsequencereset': management.get_sql_sequence_reset, - 'startapp': management.startapp, - 'startproject': management.startproject, - 'validate': management.validate, -} - -NO_SQL_TRANSACTION = ('adminindex', 'createcachetable', 'dbcheck', 'install', 'installperms', 'sqlindexes') - -def get_usage(): - """ - Returns a usage string. Doesn't do the options stuff, because optparse - takes care of that. - """ - usage = ["usage: %prog action [options]\nactions:"] - available_actions = ACTION_MAPPING.keys() - available_actions.sort() - for a in available_actions: - func = ACTION_MAPPING[a] - usage.append(" %s %s" % (a, func.args)) - usage.extend(textwrap.wrap(getattr(func, 'help_doc', func.__doc__), initial_indent=' ', subsequent_indent=' ')) - usage.append("") - return '\n'.join(usage[:-1]) # Cut off last list element, an empty space. - -class DjangoOptionParser(OptionParser): - def print_usage_and_exit(self): - self.print_help(sys.stderr) - sys.exit(1) - -def print_error(msg, cmd): - sys.stderr.write('Error: %s\nRun "%s --help" for help.\n' % (msg, cmd)) - sys.exit(1) - -def main(): - # Parse the command-line arguments. optparse handles the dirty work. - parser = DjangoOptionParser(get_usage()) - parser.add_option('--settings', - help='Python path to settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.') - parser.add_option('--pythonpath', - help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".') - options, args = parser.parse_args() - - # Take care of options. - if options.settings: - os.environ['DJANGO_SETTINGS_MODULE'] = options.settings - if options.pythonpath: - sys.path.insert(0, options.pythonpath) - - # Run the appropriate action. Unfortunately, optparse can't handle - # positional arguments, so this has to parse/validate them. - try: - action = args[0] - except IndexError: - parser.print_usage_and_exit() - if not ACTION_MAPPING.has_key(action): - print_error("Your action, %r, was invalid." % action, sys.argv[0]) - - # switch to english, because django-admin creates database content - # like permissions, and those shouldn't contain any translations. - # But only do this if we should have a working settings file. - if action not in ('startproject', 'startapp'): - from django.utils import translation - translation.activate('en-us') - - if action == 'createsuperuser': - try: - username, email, password = args[1], args[2], args[3] - except IndexError: - 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.exit(1) - else: - ACTION_MAPPING[action](username, email, password) - elif action in ('init', 'validate'): - ACTION_MAPPING[action]() - elif action == 'inspectdb': - try: - param = args[1] - except IndexError: - parser.print_usage_and_exit() - try: - 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.exit(1) - elif action == 'createcachetable': - try: - ACTION_MAPPING[action](args[1]) - except IndexError: - parser.print_usage_and_exit() - elif action in ('startapp', 'startproject'): - try: - name = args[1] - except IndexError: - parser.print_usage_and_exit() - ACTION_MAPPING[action](name, os.getcwd()) - elif action == 'runserver': - if len(args) < 2: - addr = '' - port = '8000' - else: - try: - addr, port = args[1].split(':') - except ValueError: - addr, port = '', args[1] - ACTION_MAPPING[action](addr, port) - else: - from django.core import meta - if action == 'dbcheck': - mod_list = meta.get_all_installed_modules() - else: - 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.exit(1) - if not mod_list: - parser.print_usage_and_exit() - if action not in NO_SQL_TRANSACTION: - print "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;" if __name__ == "__main__": - main() - + management.execute_from_command_line() diff --git a/django/core/management.py b/django/core/management.py index d41392d93c..7050798fb6 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -2,7 +2,8 @@ # development-server initialization. import django -import os, re, sys +import os, re, sys, textwrap +from optparse import OptionParser MODULE_TEMPLATE = ''' {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%} @@ -18,6 +19,8 @@ APP_ARGS = '[modelmodule ...]' # which has been installed. PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template') +INVALID_PROJECT_NAMES = ('django', 'test') + def _get_packages_insert(app_label): from django.core.db import db return "INSERT INTO %s (%s, %s) VALUES ('%s', '%s');" % \ @@ -471,6 +474,9 @@ def _start_helper(app_or_project, name, directory, other_name=''): def startproject(project_name, directory): "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.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') @@ -807,3 +813,150 @@ def createcachetable(tablename): curs.execute(statement) db.db.commit() createcachetable.args = "[tablename]" + +# Utilities for command-line script + +ACTION_MAPPING = { + 'adminindex': get_admin_index, + 'createsuperuser': createsuperuser, + 'createcachetable' : createcachetable, +# 'dbcheck': database_check, + 'init': init, + 'inspectdb': inspectdb, + 'install': install, + 'installperms': installperms, + 'runserver': runserver, + 'sql': get_sql_create, + 'sqlall': get_sql_all, + 'sqlclear': get_sql_delete, + 'sqlindexes': get_sql_indexes, + 'sqlinitialdata': get_sql_initial_data, + 'sqlreset': get_sql_reset, + 'sqlsequencereset': get_sql_sequence_reset, + 'startapp': startapp, + 'startproject': startproject, + 'validate': validate, +} + +NO_SQL_TRANSACTION = ('adminindex', 'createcachetable', 'dbcheck', 'install', 'installperms', 'sqlindexes') + +class DjangoOptionParser(OptionParser): + def print_usage_and_exit(self): + self.print_help(sys.stderr) + sys.exit(1) + +def get_usage(): + """ + Returns a usage string. Doesn't do the options stuff, because optparse + takes care of that. + """ + usage = ["usage: %prog action [options]\nactions:"] + available_actions = ACTION_MAPPING.keys() + available_actions.sort() + for a in available_actions: + func = ACTION_MAPPING[a] + usage.append(" %s %s" % (a, func.args)) + usage.extend(textwrap.wrap(getattr(func, 'help_doc', func.__doc__), initial_indent=' ', subsequent_indent=' ')) + usage.append("") + 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.exit(1) + +def execute_from_command_line(): + # Parse the command-line arguments. optparse handles the dirty work. + parser = DjangoOptionParser(get_usage()) + parser.add_option('--settings', + help='Python path to settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.') + parser.add_option('--pythonpath', + help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".') + options, args = parser.parse_args() + + # Take care of options. + if options.settings: + os.environ['DJANGO_SETTINGS_MODULE'] = options.settings + if options.pythonpath: + sys.path.insert(0, options.pythonpath) + + # Run the appropriate action. Unfortunately, optparse can't handle + # positional arguments, so this has to parse/validate them. + try: + action = args[0] + except IndexError: + parser.print_usage_and_exit() + if not ACTION_MAPPING.has_key(action): + print_error("Your action, %r, was invalid." % action, sys.argv[0]) + + # switch to english, because django-admin creates database content + # like permissions, and those shouldn't contain any translations. + # But only do this if we should have a working settings file. + if action not in ('startproject', 'startapp'): + from django.utils import translation + translation.activate('en-us') + + if action == 'createsuperuser': + try: + username, email, password = args[1], args[2], args[3] + except IndexError: + 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.exit(1) + else: + ACTION_MAPPING[action](username, email, password) + elif action in ('init', 'validate'): + ACTION_MAPPING[action]() + elif action == 'inspectdb': + try: + param = args[1] + except IndexError: + parser.print_usage_and_exit() + try: + 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.exit(1) + elif action == 'createcachetable': + try: + ACTION_MAPPING[action](args[1]) + except IndexError: + parser.print_usage_and_exit() + elif action in ('startapp', 'startproject'): + try: + name = args[1] + except IndexError: + parser.print_usage_and_exit() + ACTION_MAPPING[action](name, os.getcwd()) + elif action == 'runserver': + if len(args) < 2: + addr = '' + port = '8000' + else: + try: + addr, port = args[1].split(':') + except ValueError: + addr, port = '', args[1] + ACTION_MAPPING[action](addr, port) + else: + from django.core import meta + if action == 'dbcheck': + mod_list = meta.get_all_installed_modules() + else: + 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.exit(1) + if not mod_list: + parser.print_usage_and_exit() + if action not in NO_SQL_TRANSACTION: + print "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;"