web/lib/django/core/management/base.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     9 from optparse import make_option, OptionParser
     9 from optparse import make_option, OptionParser
    10 
    10 
    11 import django
    11 import django
    12 from django.core.exceptions import ImproperlyConfigured
    12 from django.core.exceptions import ImproperlyConfigured
    13 from django.core.management.color import color_style
    13 from django.core.management.color import color_style
    14 
    14 from django.utils.encoding import smart_str
    15 try:
       
    16     set
       
    17 except NameError:
       
    18     from sets import Set as set     # For Python 2.3
       
    19 
    15 
    20 class CommandError(Exception):
    16 class CommandError(Exception):
    21     """
    17     """
    22     Exception class indicating a problem while executing a management
    18     Exception class indicating a problem while executing a management
    23     command.
    19     command.
    26     command, it will be caught and turned into a nicely-printed error
    22     command, it will be caught and turned into a nicely-printed error
    27     message to the appropriate output stream (i.e., stderr); as a
    23     message to the appropriate output stream (i.e., stderr); as a
    28     result, raising this exception (with a sensible description of the
    24     result, raising this exception (with a sensible description of the
    29     error) is the preferred way to indicate that something has gone
    25     error) is the preferred way to indicate that something has gone
    30     wrong in the execution of a command.
    26     wrong in the execution of a command.
    31     
    27 
    32     """
    28     """
    33     pass
    29     pass
    34 
    30 
    35 def handle_default_options(options):
    31 def handle_default_options(options):
    36     """
    32     """
    37     Include any default options that all commands should accept here
    33     Include any default options that all commands should accept here
    38     so that ManagementUtility can handle them before searching for
    34     so that ManagementUtility can handle them before searching for
    39     user commands.
    35     user commands.
    40     
    36 
    41     """
    37     """
    42     if options.settings:
    38     if options.settings:
    43         os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
    39         os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
    44     if options.pythonpath:
    40     if options.pythonpath:
    45         sys.path.insert(0, options.pythonpath)
    41         sys.path.insert(0, options.pythonpath)
    81     all of their logic in ``handle()``, or perform some additional
    77     all of their logic in ``handle()``, or perform some additional
    82     parsing work in ``handle()`` and then delegate from it to more
    78     parsing work in ``handle()`` and then delegate from it to more
    83     specialized methods as needed.
    79     specialized methods as needed.
    84 
    80 
    85     Several attributes affect behavior at various steps along the way:
    81     Several attributes affect behavior at various steps along the way:
    86     
    82 
    87     ``args``
    83     ``args``
    88         A string listing the arguments accepted by the command,
    84         A string listing the arguments accepted by the command,
    89         suitable for use in help messages; e.g., a command which takes
    85         suitable for use in help messages; e.g., a command which takes
    90         a list of application names might set this to '<appname
    86         a list of application names might set this to '<appname
    91         appname ...>'.
    87         appname ...>'.
   115         performed prior to executing the command. Default value is
   111         performed prior to executing the command. Default value is
   116         ``True``. To validate an individual application's models
   112         ``True``. To validate an individual application's models
   117         rather than all applications' models, call
   113         rather than all applications' models, call
   118         ``self.validate(app)`` from ``handle()``, where ``app`` is the
   114         ``self.validate(app)`` from ``handle()``, where ``app`` is the
   119         application's Python module.
   115         application's Python module.
   120     
   116 
   121     """
   117     """
   122     # Metadata about this command.
   118     # Metadata about this command.
   123     option_list = (
   119     option_list = (
   124         make_option('-v', '--verbosity', action='store', dest='verbosity', default='1',
   120         make_option('-v', '--verbosity', action='store', dest='verbosity', default='1',
   125             type='choice', choices=['0', '1', '2'],
   121             type='choice', choices=['0', '1', '2'],
   145     def get_version(self):
   141     def get_version(self):
   146         """
   142         """
   147         Return the Django version, which should be correct for all
   143         Return the Django version, which should be correct for all
   148         built-in Django commands. User-supplied commands should
   144         built-in Django commands. User-supplied commands should
   149         override this method.
   145         override this method.
   150         
   146 
   151         """
   147         """
   152         return django.get_version()
   148         return django.get_version()
   153 
   149 
   154     def usage(self, subcommand):
   150     def usage(self, subcommand):
   155         """
   151         """
   156         Return a brief description of how to use this command, by
   152         Return a brief description of how to use this command, by
   157         default from the attribute ``self.help``.
   153         default from the attribute ``self.help``.
   158         
   154 
   159         """
   155         """
   160         usage = '%%prog %s [options] %s' % (subcommand, self.args)
   156         usage = '%%prog %s [options] %s' % (subcommand, self.args)
   161         if self.help:
   157         if self.help:
   162             return '%s\n\n%s' % (usage, self.help)
   158             return '%s\n\n%s' % (usage, self.help)
   163         else:
   159         else:
   165 
   161 
   166     def create_parser(self, prog_name, subcommand):
   162     def create_parser(self, prog_name, subcommand):
   167         """
   163         """
   168         Create and return the ``OptionParser`` which will be used to
   164         Create and return the ``OptionParser`` which will be used to
   169         parse the arguments to this command.
   165         parse the arguments to this command.
   170         
   166 
   171         """
   167         """
   172         return OptionParser(prog=prog_name,
   168         return OptionParser(prog=prog_name,
   173                             usage=self.usage(subcommand),
   169                             usage=self.usage(subcommand),
   174                             version=self.get_version(),
   170                             version=self.get_version(),
   175                             option_list=self.option_list)
   171                             option_list=self.option_list)
   176 
   172 
   177     def print_help(self, prog_name, subcommand):
   173     def print_help(self, prog_name, subcommand):
   178         """
   174         """
   179         Print the help message for this command, derived from
   175         Print the help message for this command, derived from
   180         ``self.usage()``.
   176         ``self.usage()``.
   181         
   177 
   182         """
   178         """
   183         parser = self.create_parser(prog_name, subcommand)
   179         parser = self.create_parser(prog_name, subcommand)
   184         parser.print_help()
   180         parser.print_help()
   185 
   181 
   186     def run_from_argv(self, argv):
   182     def run_from_argv(self, argv):
   187         """
   183         """
   188         Set up any environment changes requested (e.g., Python path
   184         Set up any environment changes requested (e.g., Python path
   189         and Django settings), then run this command.
   185         and Django settings), then run this command.
   190         
   186 
   191         """
   187         """
   192         parser = self.create_parser(argv[0], argv[1])
   188         parser = self.create_parser(argv[0], argv[1])
   193         options, args = parser.parse_args(argv[2:])
   189         options, args = parser.parse_args(argv[2:])
   194         handle_default_options(options)
   190         handle_default_options(options)
   195         self.execute(*args, **options.__dict__)
   191         self.execute(*args, **options.__dict__)
   199         Try to execute this command, performing model validation if
   195         Try to execute this command, performing model validation if
   200         needed (as controlled by the attribute
   196         needed (as controlled by the attribute
   201         ``self.requires_model_validation``). If the command raises a
   197         ``self.requires_model_validation``). If the command raises a
   202         ``CommandError``, intercept it and print it sensibly to
   198         ``CommandError``, intercept it and print it sensibly to
   203         stderr.
   199         stderr.
   204         
   200 
   205         """
   201         """
   206         # Switch to English, because django-admin.py creates database content
   202         # Switch to English, because django-admin.py creates database content
   207         # like permissions, and those shouldn't contain any translations.
   203         # like permissions, and those shouldn't contain any translations.
   208         # But only do this if we can assume we have a working settings file,
   204         # But only do this if we can assume we have a working settings file,
   209         # because django.utils.translation requires settings.
   205         # because django.utils.translation requires settings.
   212                 from django.utils import translation
   208                 from django.utils import translation
   213                 translation.activate('en-us')
   209                 translation.activate('en-us')
   214             except ImportError, e:
   210             except ImportError, e:
   215                 # If settings should be available, but aren't,
   211                 # If settings should be available, but aren't,
   216                 # raise the error and quit.
   212                 # raise the error and quit.
   217                 sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
   213                 sys.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e)))
   218                 sys.exit(1)
   214                 sys.exit(1)
   219         try:
   215         try:
   220             if self.requires_model_validation:
   216             if self.requires_model_validation:
   221                 self.validate()
   217                 self.validate()
   222             output = self.handle(*args, **options)
   218             output = self.handle(*args, **options)
   228                         print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())
   224                         print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())
   229                 print output
   225                 print output
   230                 if self.output_transaction:
   226                 if self.output_transaction:
   231                     print self.style.SQL_KEYWORD("COMMIT;")
   227                     print self.style.SQL_KEYWORD("COMMIT;")
   232         except CommandError, e:
   228         except CommandError, e:
   233             sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
   229             sys.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e)))
   234             sys.exit(1)
   230             sys.exit(1)
   235 
   231 
   236     def validate(self, app=None, display_num_errors=False):
   232     def validate(self, app=None, display_num_errors=False):
   237         """
   233         """
   238         Validates the given app, raising CommandError for any errors.
   234         Validates the given app, raising CommandError for any errors.
   239         
   235 
   240         If app is None, then this will validate all installed apps.
   236         If app is None, then this will validate all installed apps.
   241         
   237 
   242         """
   238         """
   243         from django.core.management.validation import get_validation_errors
   239         from django.core.management.validation import get_validation_errors
   244         try:
   240         try:
   245             from cStringIO import StringIO
   241             from cStringIO import StringIO
   246         except ImportError:
   242         except ImportError:
   256 
   252 
   257     def handle(self, *args, **options):
   253     def handle(self, *args, **options):
   258         """
   254         """
   259         The actual logic of the command. Subclasses must implement
   255         The actual logic of the command. Subclasses must implement
   260         this method.
   256         this method.
   261         
   257 
   262         """
   258         """
   263         raise NotImplementedError()
   259         raise NotImplementedError()
   264 
   260 
   265 class AppCommand(BaseCommand):
   261 class AppCommand(BaseCommand):
   266     """
   262     """
   267     A management command which takes one or more installed application
   263     A management command which takes one or more installed application
   268     names as arguments, and does something with each of them.
   264     names as arguments, and does something with each of them.
   269 
   265 
   270     Rather than implementing ``handle()``, subclasses must implement
   266     Rather than implementing ``handle()``, subclasses must implement
   271     ``handle_app()``, which will be called once for each application.
   267     ``handle_app()``, which will be called once for each application.
   272     
   268 
   273     """
   269     """
   274     args = '<appname appname ...>'
   270     args = '<appname appname ...>'
   275 
   271 
   276     def handle(self, *app_labels, **options):
   272     def handle(self, *app_labels, **options):
   277         from django.db import models
   273         from django.db import models
   291     def handle_app(self, app, **options):
   287     def handle_app(self, app, **options):
   292         """
   288         """
   293         Perform the command's actions for ``app``, which will be the
   289         Perform the command's actions for ``app``, which will be the
   294         Python module corresponding to an application name given on
   290         Python module corresponding to an application name given on
   295         the command line.
   291         the command line.
   296         
   292 
   297         """
   293         """
   298         raise NotImplementedError()
   294         raise NotImplementedError()
   299 
   295 
   300 class LabelCommand(BaseCommand):
   296 class LabelCommand(BaseCommand):
   301     """
   297     """
   306     Rather than implementing ``handle()``, subclasses must implement
   302     Rather than implementing ``handle()``, subclasses must implement
   307     ``handle_label()``, which will be called once for each label.
   303     ``handle_label()``, which will be called once for each label.
   308 
   304 
   309     If the arguments should be names of installed applications, use
   305     If the arguments should be names of installed applications, use
   310     ``AppCommand`` instead.
   306     ``AppCommand`` instead.
   311     
   307 
   312     """
   308     """
   313     args = '<label label ...>'
   309     args = '<label label ...>'
   314     label = 'label'
   310     label = 'label'
   315 
   311 
   316     def handle(self, *labels, **options):
   312     def handle(self, *labels, **options):
   326 
   322 
   327     def handle_label(self, label, **options):
   323     def handle_label(self, label, **options):
   328         """
   324         """
   329         Perform the command's actions for ``label``, which will be the
   325         Perform the command's actions for ``label``, which will be the
   330         string as given on the command line.
   326         string as given on the command line.
   331         
   327 
   332         """
   328         """
   333         raise NotImplementedError()
   329         raise NotImplementedError()
   334 
   330 
   335 class NoArgsCommand(BaseCommand):
   331 class NoArgsCommand(BaseCommand):
   336     """
   332     """
   339     Rather than implementing ``handle()``, subclasses must implement
   335     Rather than implementing ``handle()``, subclasses must implement
   340     ``handle_noargs()``; ``handle()`` itself is overridden to ensure
   336     ``handle_noargs()``; ``handle()`` itself is overridden to ensure
   341     no arguments are passed to the command.
   337     no arguments are passed to the command.
   342 
   338 
   343     Attempting to pass arguments will raise ``CommandError``.
   339     Attempting to pass arguments will raise ``CommandError``.
   344     
   340 
   345     """
   341     """
   346     args = ''
   342     args = ''
   347 
   343 
   348     def handle(self, *args, **options):
   344     def handle(self, *args, **options):
   349         if args:
   345         if args:
   351         return self.handle_noargs(**options)
   347         return self.handle_noargs(**options)
   352 
   348 
   353     def handle_noargs(self, **options):
   349     def handle_noargs(self, **options):
   354         """
   350         """
   355         Perform this command's actions.
   351         Perform this command's actions.
   356         
   352 
   357         """
   353         """
   358         raise NotImplementedError()
   354         raise NotImplementedError()
   359 
   355 
   360 def copy_helper(style, app_or_project, name, directory, other_name=''):
   356 def copy_helper(style, app_or_project, name, directory, other_name=''):
   361     """
   357     """
   417 
   413 
   418 def _make_writeable(filename):
   414 def _make_writeable(filename):
   419     """
   415     """
   420     Make sure that the file is writeable. Useful if our source is
   416     Make sure that the file is writeable. Useful if our source is
   421     read-only.
   417     read-only.
   422     
   418 
   423     """
   419     """
   424     import stat
   420     import stat
   425     if sys.platform.startswith('java'):
   421     if sys.platform.startswith('java'):
   426         # On Jython there is no os.access()
   422         # On Jython there is no os.access()
   427         return
   423         return