diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py index d39d69eff1..a4731652f5 100644 --- a/django/core/management/__init__.py +++ b/django/core/management/__init__.py @@ -2,7 +2,6 @@ import django from optparse import OptionParser import os import sys -import textwrap # For backwards compatibility: get_version() used to be in this module. get_version = django.get_version @@ -36,7 +35,9 @@ class ManagementUtility(object): A ManagementUtility has a number of commands, which can be manipulated by editing the self.commands dictionary. """ - def __init__(self): + def __init__(self, argv=None): + self.argv = argv or sys.argv[:] + self.prog_name = os.path.basename(self.argv[0]) self.commands = self.default_commands() def default_commands(self): @@ -52,22 +53,21 @@ class ManagementUtility(object): names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')] return dict([(name, load_command_class(name)) for name in names]) - def print_help(self, argv): + def main_help_text(self): """ - Returns the help message, as a string. + Returns the script's main help text, as a string. """ - prog_name = os.path.basename(argv[0]) - usage = ['%s [options] [args]' % prog_name] + usage = ['%s [options] [args]' % self.prog_name] usage.append('Django command line tool, version %s' % django.get_version()) - usage.append("Type '%s help ' for help on a specific subcommand." % prog_name) + usage.append("Type '%s help ' for help on a specific subcommand." % self.prog_name) usage.append('Available subcommands:') commands = self.commands.keys() commands.sort() for cmd in commands: usage.append(' %s' % cmd) - print '\n'.join(usage) + return '\n'.join(usage) - def fetch_command(self, subcommand, command_name): + def fetch_command(self, subcommand): """ Tries to fetch the given subcommand, printing a message with the appropriate command called from the command line (usually @@ -76,35 +76,34 @@ class ManagementUtility(object): try: return self.commands[subcommand] except KeyError: - sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, command_name)) + sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, self.prog_name)) sys.exit(1) - def execute(self, argv=None): + def execute(self): """ - Figures out which command is being run (the first arg), creates a parser - appropriate to that command, and runs it. + Given the command-line arguments, this figures out which subcommand is + being run, creates a parser appropriate to that command, and runs it. """ - if argv is None: - argv = sys.argv try: - command_name = argv[1] + subcommand = self.argv[1] except IndexError: - sys.stderr.write("Type '%s help' for usage.\n" % os.path.basename(argv[0])) + sys.stderr.write("Type '%s help' for usage.\n" % self.prog_name) sys.exit(1) - if command_name == 'help': - if len(argv) > 2: - self.fetch_command(argv[2], argv[0]).print_help(argv[2:]) + if subcommand == 'help': + if len(self.argv) > 2: + self.fetch_command(self.argv[2]).print_help(self.prog_name, self.argv[2]) else: - self.print_help(argv) + sys.stderr.write(self.main_help_text() + '\n') + sys.exit(1) # Special-cases: We want 'django-admin.py --version' and # 'django-admin.py --help' to work, for backwards compatibility. - elif argv[1:] == ['--version']: + elif self.argv[1:] == ['--version']: print django.get_version() - elif argv[1:] == ['--help']: - self.print_help(argv) + elif self.argv[1:] == ['--help']: + sys.stderr.write(self.main_help_text() + '\n') else: - self.fetch_command(command_name, argv[0]).run(argv[1:]) + self.fetch_command(subcommand).run_from_argv(self.argv) class ProjectManagementUtility(ManagementUtility): """ @@ -115,8 +114,8 @@ class ProjectManagementUtility(ManagementUtility): In practice, this class represents manage.py, whereas ManagementUtility represents django-admin.py. """ - def __init__(self, project_directory): - super(ProjectManagementUtility, self).__init__() + def __init__(self, argv, project_directory): + super(ProjectManagementUtility, self).__init__(argv) # Remove the "startproject" command from self.commands, because # that's a django-admin.py command, not a manage.py command. @@ -150,8 +149,8 @@ def execute_from_command_line(argv=None): """ A simple method that runs a ManagementUtility. """ - utility = ManagementUtility() - utility.execute(argv) + utility = ManagementUtility(argv) + utility.execute() def execute_manager(settings_mod, argv=None): """ @@ -159,5 +158,5 @@ def execute_manager(settings_mod, argv=None): project-specific django-admin.py utility. """ project_directory = setup_environ(settings_mod) - utility = ProjectManagementUtility(project_directory) - utility.execute(argv) + utility = ProjectManagementUtility(argv, project_directory) + utility.execute() diff --git a/django/core/management/base.py b/django/core/management/base.py index fb43895b51..83b0ed05cd 100644 --- a/django/core/management/base.py +++ b/django/core/management/base.py @@ -5,7 +5,6 @@ import itertools from optparse import make_option, OptionParser import sys import os -from traceback import print_exc class CommandError(Exception): pass @@ -36,35 +35,31 @@ class BaseCommand(object): """ return django.get_version() - def usage(self): - usage = '%prog [options] ' + self.args + def usage(self, subcommand): + usage = '%%prog %s [options] %s' % (subcommand, self.args) if self.help: return '%s\n\n%s' % (usage, self.help) else: return usage - def create_parser(self, prog_name): + def create_parser(self, prog_name, subcommand): return OptionParser(prog=prog_name, - usage=self.usage(), + usage=self.usage(subcommand), version=self.get_version(), option_list=self.option_list) - def print_help(self, args): - parser = self.create_parser(args[0]) + def print_help(self, prog_name, subcommand): + parser = self.create_parser(prog_name, subcommand) parser.print_help() - def run(self, args): - parser = self.create_parser(args[0]) - (options, args) = parser.parse_args(args[1:]) + def run_from_argv(self, argv): + parser = self.create_parser(argv[0], argv[1]) + options, args = parser.parse_args(argv[2:]) if options.settings: os.environ['DJANGO_SETTINGS_MODULE'] = options.settings if options.pythonpath: sys.path.insert(0, options.pythonpath) - try: - self.execute(*args, **options.__dict__) - except Exception, e: - print_exc() - parser.print_usage() + self.execute(*args, **options.__dict__) def execute(self, *args, **options): # Switch to English, because django-admin.py creates database content diff --git a/django/core/management/commands/runfcgi.py b/django/core/management/commands/runfcgi.py index 599ac2dcd2..a60d4ebc59 100644 --- a/django/core/management/commands/runfcgi.py +++ b/django/core/management/commands/runfcgi.py @@ -15,6 +15,6 @@ class Command(BaseCommand): from django.core.servers.fastcgi import runfastcgi runfastcgi(args) - def usage(self): + def usage(self, subcommand): from django.core.servers.fastcgi import FASTCGI_HELP return FASTCGI_HELP diff --git a/django/db/models/loading.py b/django/db/models/loading.py index 090390aa9e..e7d134e6da 100644 --- a/django/db/models/loading.py +++ b/django/db/models/loading.py @@ -52,11 +52,7 @@ class AppCache(object): for app_name in settings.INSTALLED_APPS: if app_name in self.handled: continue - try: - self.load_app(app_name, True) - except Exception, e: - # Problem importing the app - self.app_errors[app_name] = e + self.load_app(app_name, True) if not self.nesting_level: for app_name in self.postponed: self.load_app(app_name) diff --git a/docs/contributing.txt b/docs/contributing.txt index f1ad0e3bb0..4ec5c3c2af 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -417,6 +417,44 @@ Documentation style We place a high importance on consistency and readability of documentation. (After all, Django was created in a journalism environment!) +How to document new features +---------------------------- + +We treat our documentation like we treat our code: we aim to improve it as +often as possible. This section explains how writers can craft their +documentation changes in the most useful and least error-prone ways. + +Documentation changes come in two forms: + + * General improvements -- Typo corrections, error fixes and better + explanations through clearer writing and more examples. + + * New features -- Documentation of features that have been added to the + framework since the last release. + +Our philosophy is that "general improvements" are something that *all* current +Django users should benefit from, including users of trunk *and* users of the +latest release. Hence, the documentation section on djangoproject.com points +people by default to the newest versions of the docs, because they have the +latest and greatest content. (In fact, the Web site pulls directly from the +Subversion repository, converting to HTML on the fly.) + +But this decision to feature bleeding-edge documentation has one large caveat: +any documentation of *new* features will be seen by Django users who don't +necessarily have access to those features yet, because they're only using the +latest release. Thus, our policy is: + + **All documentation of new features should be written in a way that clearly + designates the features are only available in the Django development + version. Assume documentation readers are using the latest release, not the + development version.** + +Our traditional way of marking new features is by prefacing the features' +documentation with: "New in Django development version." Changes aren't +*required* to include this exact text, but all documentation of new features +should include the phrase "development version," so we can find and remove +those phrases for the next release. + Guidelines for ReST files ------------------------- diff --git a/tests/regressiontests/forms/regressions.py b/tests/regressiontests/forms/regressions.py index 784ef49902..df2ef578a1 100644 --- a/tests/regressiontests/forms/regressions.py +++ b/tests/regressiontests/forms/regressions.py @@ -64,20 +64,6 @@ u'
  • \u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u04 # Miscellaneous Tests # ####################### -There once was a problem with Form fields called "data". Let's make sure that -doesn't come back. ->>> class DataForm(Form): -... data = CharField(max_length=10) ->>> f = DataForm({'data': 'xyzzy'}) ->>> f.is_valid() -True ->>> f.cleaned_data -{'data': u'xyzzy'} - -####################### -# Miscellaneous Tests # -####################### - There once was a problem with Form fields called "data". Let's make sure that doesn't come back. >>> class DataForm(Form):