mirror of
				https://github.com/django/django.git
				synced 2025-10-29 16:46:11 +00:00 
			
		
		
		
	Improved error handling for management.py commands, especially for no argument or non-applabel argument commands.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5903 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -65,6 +65,7 @@ class BaseCommand(object): | ||||
|     def handle(self, *args, **options): | ||||
|         raise NotImplementedError() | ||||
|  | ||||
|  | ||||
| class AppCommand(BaseCommand): | ||||
|     args = '[appname ...]' | ||||
|  | ||||
| @@ -86,46 +87,77 @@ class AppCommand(BaseCommand): | ||||
|     def handle_app(self, app, **options): | ||||
|         raise NotImplementedError() | ||||
|  | ||||
| class CopyFilesCommand(BaseCommand): | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def copy_helper(self, app_or_project, name, directory, other_name=''): | ||||
|         import django | ||||
|         import os | ||||
|         import re | ||||
|         import shutil | ||||
|         other = {'project': 'app', 'app': 'project'}[app_or_project] | ||||
|         if not re.search(r'^\w+$', name): # If it's not a valid directory name. | ||||
|             raise CommandError("%r is not a valid %s name. Please use only numbers, letters and underscores." % (name, app_or_project)) | ||||
|         top_dir = os.path.join(directory, name) | ||||
|         try: | ||||
|             os.mkdir(top_dir) | ||||
|         except OSError, e: | ||||
|             raise CommandError(e) | ||||
| class LabelCommand(BaseCommand): | ||||
|     args = '[label ...]' | ||||
|     label = 'label' | ||||
|      | ||||
|     def handle(self, *labels, **options): | ||||
|         if not labels: | ||||
|             raise CommandError('Enter at least one %s.' % self.label) | ||||
|  | ||||
|         # Determine where the app or project templates are. Use | ||||
|         # django.__path__[0] because we don't know into which directory | ||||
|         # django has been installed. | ||||
|         template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project) | ||||
|         output = [] | ||||
|         for label in labels: | ||||
|             label_output = self.handle_label(label, **options) | ||||
|             if label_output: | ||||
|                 output.append(label_output) | ||||
|         return '\n'.join(output) | ||||
|  | ||||
|         for d, subdirs, files in os.walk(template_dir): | ||||
|             relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name) | ||||
|             if relative_dir: | ||||
|                 os.mkdir(os.path.join(top_dir, relative_dir)) | ||||
|             for i, subdir in enumerate(subdirs): | ||||
|                 if subdir.startswith('.'): | ||||
|                     del subdirs[i] | ||||
|             for f in files: | ||||
|                 if f.endswith('.pyc'): | ||||
|                     continue | ||||
|                 path_old = os.path.join(d, f) | ||||
|                 path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name)) | ||||
|                 fp_old = open(path_old, 'r') | ||||
|                 fp_new = open(path_new, 'w') | ||||
|                 fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name)) | ||||
|                 fp_old.close() | ||||
|                 fp_new.close() | ||||
|                 try: | ||||
|                     shutil.copymode(path_old, path_new) | ||||
|                 except OSError: | ||||
|                     sys.stderr.write(self.style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new)) | ||||
|     def handle_label(self, label, **options): | ||||
|         raise NotImplementedError() | ||||
|  | ||||
|  | ||||
| class NoArgsCommand(BaseCommand): | ||||
|     args = '' | ||||
|  | ||||
|     def handle(self, *args, **options): | ||||
|         from django.db import models | ||||
|         if len(args) != 0: | ||||
|             raise CommandError("Command doesn't accept any arguments") | ||||
|  | ||||
|         return self.handle_noargs(**options) | ||||
|  | ||||
|     def handle_noargs(self, **options): | ||||
|         raise NotImplementedError() | ||||
|  | ||||
|      | ||||
| def copy_helper(app_or_project, name, directory, other_name=''): | ||||
|     import django | ||||
|     import os | ||||
|     import re | ||||
|     import shutil | ||||
|     other = {'project': 'app', 'app': 'project'}[app_or_project] | ||||
|     if not re.search(r'^\w+$', name): # If it's not a valid directory name. | ||||
|         raise CommandError("%r is not a valid %s name. Please use only numbers, letters and underscores." % (name, app_or_project)) | ||||
|     top_dir = os.path.join(directory, name) | ||||
|     try: | ||||
|         os.mkdir(top_dir) | ||||
|     except OSError, e: | ||||
|         raise CommandError(e) | ||||
|  | ||||
|     # Determine where the app or project templates are. Use | ||||
|     # django.__path__[0] because we don't know into which directory | ||||
|     # django has been installed. | ||||
|     template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project) | ||||
|  | ||||
|     for d, subdirs, files in os.walk(template_dir): | ||||
|         relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name) | ||||
|         if relative_dir: | ||||
|             os.mkdir(os.path.join(top_dir, relative_dir)) | ||||
|         for i, subdir in enumerate(subdirs): | ||||
|             if subdir.startswith('.'): | ||||
|                 del subdirs[i] | ||||
|         for f in files: | ||||
|             if f.endswith('.pyc'): | ||||
|                 continue | ||||
|             path_old = os.path.join(d, f) | ||||
|             path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name)) | ||||
|             fp_old = open(path_old, 'r') | ||||
|             fp_new = open(path_new, 'w') | ||||
|             fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name)) | ||||
|             fp_old.close() | ||||
|             fp_new.close() | ||||
|             try: | ||||
|                 shutil.copymode(path_old, path_new) | ||||
|             except OSError: | ||||
|                 sys.stderr.write(self.style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new)) | ||||
|   | ||||
| @@ -1,12 +1,13 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.core.management.base import LabelCommand | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(LabelCommand): | ||||
|     help = "Creates the table needed to use the SQL cache backend." | ||||
|     args = "[tablename]" | ||||
|     label = 'tablename' | ||||
|  | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def handle(self, tablename, **options): | ||||
|     def handle_label(self, tablename, **options): | ||||
|         from django.db import backend, connection, transaction, models | ||||
|         fields = ( | ||||
|             # "key" is a reserved word in MySQL, so use "cache_key" instead. | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.core.management.base import NoArgsCommand | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = "Runs the command-line client for the current DATABASE_ENGINE." | ||||
|  | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         from django.db import runshell | ||||
|         runshell() | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.core.management.base import NoArgsCommand | ||||
|  | ||||
| def module_to_dict(module, omittable=lambda k: k.startswith('_')): | ||||
|     "Converts a module namespace to a Python dictionary. Used by get_settings_diff." | ||||
|     return dict([(k, repr(v)) for k, v in module.__dict__.items() if not omittable(k)]) | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = """Displays differences between the current settings.py and Django's | ||||
|     default settings. Settings that don't appear in the defaults are | ||||
|     followed by "###".""" | ||||
|  | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         # Inspired by Postfix's "postconf -n". | ||||
|         from django.conf import settings, global_settings | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| from django.core.management.base import BaseCommand, CommandError | ||||
| from django.core.management.base import NoArgsCommand, CommandError | ||||
| from django.core.management.color import no_style | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = "Executes ``sqlflush`` on the current database." | ||||
|     args = '[--verbosity] [--noinput]' | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         from django.conf import settings | ||||
|         from django.db import connection, transaction, models | ||||
|         from django.dispatch import dispatcher | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| from django.core.management.base import BaseCommand, CommandError | ||||
| from django.core.management.base import NoArgsCommand, CommandError | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = "Introspects the database tables in the given database and outputs a Django model module." | ||||
|  | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         try: | ||||
|             for line in self.handle_inspection(): | ||||
|                 print line | ||||
|   | ||||
| @@ -9,10 +9,12 @@ class Command(BaseCommand): | ||||
|     # Validation is called explicitly each time the server is reloaded. | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def handle(self, addrport='', **options): | ||||
|     def handle(self, addrport='', *args, **options): | ||||
|         import django | ||||
|         from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException | ||||
|         from django.core.handlers.wsgi import WSGIHandler | ||||
|         if len(args) != 0: | ||||
|             raise CommandError('Usage is runserver %s' % self.args) | ||||
|         if not addrport: | ||||
|             addr = '' | ||||
|             port = '8000' | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.core.management.base import NoArgsCommand | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = "Runs a Python interactive interpreter. Tries to use IPython, if it's available." | ||||
|     args = '[--plain]' | ||||
|  | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         # XXX: (Temporary) workaround for ticket #1796: force early loading of all | ||||
|         # models from installed apps. | ||||
|         from django.db.models.loading import get_models | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.core.management.base import NoArgsCommand | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = "Returns a list of the SQL statements required to return all tables in the database to the state they were in just after they were installed." | ||||
|  | ||||
|     output_transaction = True | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         from django.core.management.sql import sql_flush | ||||
|         return '\n'.join(sql_flush(self.style)) | ||||
|   | ||||
| @@ -1,16 +1,17 @@ | ||||
| from django.core.management.base import CopyFilesCommand, CommandError | ||||
| from django.core.management.base import copy_helper, CommandError, LabelCommand | ||||
| import os | ||||
|  | ||||
| class Command(CopyFilesCommand): | ||||
| class Command(LabelCommand): | ||||
|     help = "Creates a Django app directory structure for the given app name in the current directory." | ||||
|     args = "[appname]" | ||||
|     label = 'application name' | ||||
|  | ||||
|     requires_model_validation = False | ||||
|     # Can't import settings during this command, because they haven't | ||||
|     # necessarily been created. | ||||
|     can_import_settings = False | ||||
|  | ||||
|     def handle(self, app_name, directory=None, **options): | ||||
|     def handle_label(self, app_name, directory=None, **options): | ||||
|         if directory is None: | ||||
|             directory = os.getcwd() | ||||
|         # Determine the project_name a bit naively -- by looking at the name of | ||||
| @@ -20,7 +21,7 @@ class Command(CopyFilesCommand): | ||||
|         project_name = os.path.basename(directory) | ||||
|         if app_name == project_name: | ||||
|             raise CommandError("You cannot create an app with the same name (%r) as your project." % app_name) | ||||
|         self.copy_helper('app', app_name, directory, parent_dir) | ||||
|         copy_helper('app', app_name, directory, parent_dir) | ||||
|  | ||||
| class ProjectCommand(Command): | ||||
|     help = "Creates a Django app directory structure for the given app name in this project's directory." | ||||
| @@ -29,5 +30,5 @@ class ProjectCommand(Command): | ||||
|         super(ProjectCommand, self).__init__() | ||||
|         self.project_directory = project_directory | ||||
|  | ||||
|     def handle(self, app_name, **options): | ||||
|         super(ProjectCommand, self).handle(app_name, self.project_directory, **options) | ||||
|     def handle_label(self, app_name, **options): | ||||
|         super(ProjectCommand, self).handle_label(app_name, self.project_directory, **options) | ||||
|   | ||||
| @@ -1,20 +1,21 @@ | ||||
| from django.core.management.base import CopyFilesCommand, CommandError | ||||
| from django.core.management.base import copy_helper, CommandError, LabelCommand | ||||
| import os | ||||
| import re | ||||
| from random import choice | ||||
|  | ||||
| INVALID_PROJECT_NAMES = ('django', 'site', 'test') | ||||
|  | ||||
| class Command(CopyFilesCommand): | ||||
| class Command(LabelCommand): | ||||
|     help = "Creates a Django project directory structure for the given project name in the current directory." | ||||
|     args = "[projectname]" | ||||
|     label = 'project name' | ||||
|  | ||||
|     requires_model_validation = False | ||||
|     # Can't import settings during this command, because they haven't | ||||
|     # necessarily been created. | ||||
|     can_import_settings = False | ||||
|  | ||||
|     def handle(self, project_name, **options): | ||||
|     def handle_label(self, project_name, **options): | ||||
|         # Determine the project_name a bit naively -- by looking at the name of | ||||
|         # the parent directory. | ||||
|         directory = os.getcwd() | ||||
| @@ -22,7 +23,7 @@ class Command(CopyFilesCommand): | ||||
|         if project_name in INVALID_PROJECT_NAMES: | ||||
|             raise CommandError("%r conflicts with the name of an existing Python module and cannot be used as a project name. Please try another name." % project_name) | ||||
|  | ||||
|         self.copy_helper('project', project_name, directory) | ||||
|         copy_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') | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.core.management.base import NoArgsCommand | ||||
| from django.core.management.color import no_style | ||||
|  | ||||
| try: | ||||
| @@ -6,15 +6,15 @@ try: | ||||
| except NameError: | ||||
|     from sets import Set as set   # Python 2.3 fallback | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." | ||||
|     args = '[--verbosity] [--noinput]' | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         from django.db import backend, connection, transaction, models | ||||
|         from django.conf import settings | ||||
|         from django.core.management.sql import table_list, installed_models, sql_model_create, sql_for_pending_references, many_to_many_sql_for_model, custom_sql_for_model, sql_indexes_for_model, emit_post_sync_signal | ||||
|  | ||||
|              | ||||
|         verbosity = int(options.get('verbosity', 1)) | ||||
|         interactive = options.get('interactive') | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.core.management.base import NoArgsCommand | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| class Command(NoArgsCommand): | ||||
|     help = "Validates all installed models." | ||||
|  | ||||
|     requires_model_validation = False | ||||
|  | ||||
|     def handle(self, **options): | ||||
|     def handle_noargs(self, **options): | ||||
|         self.validate() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user