mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +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): |     def handle(self, *args, **options): | ||||||
|         raise NotImplementedError() |         raise NotImplementedError() | ||||||
|  |  | ||||||
|  |  | ||||||
| class AppCommand(BaseCommand): | class AppCommand(BaseCommand): | ||||||
|     args = '[appname ...]' |     args = '[appname ...]' | ||||||
|  |  | ||||||
| @@ -86,46 +87,77 @@ class AppCommand(BaseCommand): | |||||||
|     def handle_app(self, app, **options): |     def handle_app(self, app, **options): | ||||||
|         raise NotImplementedError() |         raise NotImplementedError() | ||||||
|  |  | ||||||
| class CopyFilesCommand(BaseCommand): |  | ||||||
|     requires_model_validation = False |  | ||||||
|  |  | ||||||
|     def copy_helper(self, app_or_project, name, directory, other_name=''): | class LabelCommand(BaseCommand): | ||||||
|         import django |     args = '[label ...]' | ||||||
|         import os |     label = 'label' | ||||||
|         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 |     def handle(self, *labels, **options): | ||||||
|         # django.__path__[0] because we don't know into which directory |         if not labels: | ||||||
|         # django has been installed. |             raise CommandError('Enter at least one %s.' % self.label) | ||||||
|         template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project) |  | ||||||
|  |  | ||||||
|         for d, subdirs, files in os.walk(template_dir): |         output = [] | ||||||
|             relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name) |         for label in labels: | ||||||
|             if relative_dir: |             label_output = self.handle_label(label, **options) | ||||||
|                 os.mkdir(os.path.join(top_dir, relative_dir)) |             if label_output: | ||||||
|             for i, subdir in enumerate(subdirs): |                 output.append(label_output) | ||||||
|                 if subdir.startswith('.'): |         return '\n'.join(output) | ||||||
|                     del subdirs[i] |  | ||||||
|             for f in files: |     def handle_label(self, label, **options): | ||||||
|                 if f.endswith('.pyc'): |         raise NotImplementedError() | ||||||
|                     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)) | class NoArgsCommand(BaseCommand): | ||||||
|                 fp_old = open(path_old, 'r') |     args = '' | ||||||
|                 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)) |     def handle(self, *args, **options): | ||||||
|                 fp_old.close() |         from django.db import models | ||||||
|                 fp_new.close() |         if len(args) != 0: | ||||||
|                 try: |             raise CommandError("Command doesn't accept any arguments") | ||||||
|                     shutil.copymode(path_old, path_new) |  | ||||||
|                 except OSError: |         return self.handle_noargs(**options) | ||||||
|                     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_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." |     help = "Creates the table needed to use the SQL cache backend." | ||||||
|     args = "[tablename]" |     args = "[tablename]" | ||||||
|  |     label = 'tablename' | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|  |  | ||||||
|     def handle(self, tablename, **options): |     def handle_label(self, tablename, **options): | ||||||
|         from django.db import backend, connection, transaction, models |         from django.db import backend, connection, transaction, models | ||||||
|         fields = ( |         fields = ( | ||||||
|             # "key" is a reserved word in MySQL, so use "cache_key" instead. |             # "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." |     help = "Runs the command-line client for the current DATABASE_ENGINE." | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         from django.db import runshell |         from django.db import runshell | ||||||
|         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('_')): | def module_to_dict(module, omittable=lambda k: k.startswith('_')): | ||||||
|     "Converts a module namespace to a Python dictionary. Used by get_settings_diff." |     "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)]) |     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 |     help = """Displays differences between the current settings.py and Django's | ||||||
|     default settings. Settings that don't appear in the defaults are |     default settings. Settings that don't appear in the defaults are | ||||||
|     followed by "###".""" |     followed by "###".""" | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         # Inspired by Postfix's "postconf -n". |         # Inspired by Postfix's "postconf -n". | ||||||
|         from django.conf import settings, global_settings |         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 | from django.core.management.color import no_style | ||||||
|  |  | ||||||
| class Command(BaseCommand): | class Command(NoArgsCommand): | ||||||
|     help = "Executes ``sqlflush`` on the current database." |     help = "Executes ``sqlflush`` on the current database." | ||||||
|     args = '[--verbosity] [--noinput]' |     args = '[--verbosity] [--noinput]' | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         from django.conf import settings |         from django.conf import settings | ||||||
|         from django.db import connection, transaction, models |         from django.db import connection, transaction, models | ||||||
|         from django.dispatch import dispatcher |         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." |     help = "Introspects the database tables in the given database and outputs a Django model module." | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         try: |         try: | ||||||
|             for line in self.handle_inspection(): |             for line in self.handle_inspection(): | ||||||
|                 print line |                 print line | ||||||
|   | |||||||
| @@ -9,10 +9,12 @@ class Command(BaseCommand): | |||||||
|     # Validation is called explicitly each time the server is reloaded. |     # Validation is called explicitly each time the server is reloaded. | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|  |  | ||||||
|     def handle(self, addrport='', **options): |     def handle(self, addrport='', *args, **options): | ||||||
|         import django |         import django | ||||||
|         from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException |         from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException | ||||||
|         from django.core.handlers.wsgi import WSGIHandler |         from django.core.handlers.wsgi import WSGIHandler | ||||||
|  |         if len(args) != 0: | ||||||
|  |             raise CommandError('Usage is runserver %s' % self.args) | ||||||
|         if not addrport: |         if not addrport: | ||||||
|             addr = '' |             addr = '' | ||||||
|             port = '8000' |             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." |     help = "Runs a Python interactive interpreter. Tries to use IPython, if it's available." | ||||||
|     args = '[--plain]' |     args = '[--plain]' | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         # XXX: (Temporary) workaround for ticket #1796: force early loading of all |         # XXX: (Temporary) workaround for ticket #1796: force early loading of all | ||||||
|         # models from installed apps. |         # models from installed apps. | ||||||
|         from django.db.models.loading import get_models |         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." |     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 |     output_transaction = True | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         from django.core.management.sql import sql_flush |         from django.core.management.sql import sql_flush | ||||||
|         return '\n'.join(sql_flush(self.style)) |         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 | import os | ||||||
|  |  | ||||||
| class Command(CopyFilesCommand): | class Command(LabelCommand): | ||||||
|     help = "Creates a Django app directory structure for the given app name in the current directory." |     help = "Creates a Django app directory structure for the given app name in the current directory." | ||||||
|     args = "[appname]" |     args = "[appname]" | ||||||
|  |     label = 'application name' | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|     # Can't import settings during this command, because they haven't |     # Can't import settings during this command, because they haven't | ||||||
|     # necessarily been created. |     # necessarily been created. | ||||||
|     can_import_settings = False |     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: |         if directory is None: | ||||||
|             directory = os.getcwd() |             directory = os.getcwd() | ||||||
|         # Determine the project_name a bit naively -- by looking at the name of |         # 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) |         project_name = os.path.basename(directory) | ||||||
|         if app_name == project_name: |         if app_name == project_name: | ||||||
|             raise CommandError("You cannot create an app with the same name (%r) as your project." % app_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): | class ProjectCommand(Command): | ||||||
|     help = "Creates a Django app directory structure for the given app name in this project's directory." |     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__() |         super(ProjectCommand, self).__init__() | ||||||
|         self.project_directory = project_directory |         self.project_directory = project_directory | ||||||
|  |  | ||||||
|     def handle(self, app_name, **options): |     def handle_label(self, app_name, **options): | ||||||
|         super(ProjectCommand, self).handle(app_name, self.project_directory, **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 os | ||||||
| import re | import re | ||||||
| from random import choice | from random import choice | ||||||
|  |  | ||||||
| INVALID_PROJECT_NAMES = ('django', 'site', 'test') | 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." |     help = "Creates a Django project directory structure for the given project name in the current directory." | ||||||
|     args = "[projectname]" |     args = "[projectname]" | ||||||
|  |     label = 'project name' | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|     # Can't import settings during this command, because they haven't |     # Can't import settings during this command, because they haven't | ||||||
|     # necessarily been created. |     # necessarily been created. | ||||||
|     can_import_settings = False |     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 |         # Determine the project_name a bit naively -- by looking at the name of | ||||||
|         # the parent directory. |         # the parent directory. | ||||||
|         directory = os.getcwd() |         directory = os.getcwd() | ||||||
| @@ -22,7 +23,7 @@ class Command(CopyFilesCommand): | |||||||
|         if project_name in INVALID_PROJECT_NAMES: |         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) |             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. |         # Create a random SECRET_KEY hash, and put it in the main settings. | ||||||
|         main_settings_file = os.path.join(directory, project_name, 'settings.py') |         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 | from django.core.management.color import no_style | ||||||
|  |  | ||||||
| try: | try: | ||||||
| @@ -6,11 +6,11 @@ try: | |||||||
| except NameError: | except NameError: | ||||||
|     from sets import Set as set   # Python 2.3 fallback |     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." |     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." | ||||||
|     args = '[--verbosity] [--noinput]' |     args = '[--verbosity] [--noinput]' | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         from django.db import backend, connection, transaction, models |         from django.db import backend, connection, transaction, models | ||||||
|         from django.conf import settings |         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 |         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 | ||||||
|   | |||||||
| @@ -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." |     help = "Validates all installed models." | ||||||
|  |  | ||||||
|     requires_model_validation = False |     requires_model_validation = False | ||||||
|  |  | ||||||
|     def handle(self, **options): |     def handle_noargs(self, **options): | ||||||
|         self.validate() |         self.validate() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user