diff --git a/django/contrib/auth/management/commands/createsuperuser.py b/django/contrib/auth/management/commands/createsuperuser.py
index ad65977..f3f1a7b 100644
a
|
b
|
class Command(BaseCommand):
|
80 | 80 | if default_username and username == '': |
81 | 81 | username = default_username |
82 | 82 | if not RE_VALID_USERNAME.match(username): |
83 | | sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n") |
| 83 | self.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.") |
84 | 84 | username = None |
85 | 85 | continue |
86 | 86 | try: |
… |
… |
class Command(BaseCommand):
|
88 | 88 | except User.DoesNotExist: |
89 | 89 | break |
90 | 90 | else: |
91 | | sys.stderr.write("Error: That username is already taken.\n") |
| 91 | self.stderr.write("Error: That username is already taken.") |
92 | 92 | username = None |
93 | 93 | |
94 | 94 | # Get an email |
… |
… |
class Command(BaseCommand):
|
98 | 98 | try: |
99 | 99 | is_valid_email(email) |
100 | 100 | except exceptions.ValidationError: |
101 | | sys.stderr.write("Error: That e-mail address is invalid.\n") |
| 101 | self.stderr.write("Error: That e-mail address is invalid.") |
102 | 102 | email = None |
103 | 103 | else: |
104 | 104 | break |
… |
… |
class Command(BaseCommand):
|
109 | 109 | password = getpass.getpass() |
110 | 110 | password2 = getpass.getpass('Password (again): ') |
111 | 111 | if password != password2: |
112 | | sys.stderr.write("Error: Your passwords didn't match.\n") |
| 112 | self.stderr.write("Error: Your passwords didn't match.") |
113 | 113 | password = None |
114 | 114 | continue |
115 | 115 | if password.strip() == '': |
116 | | sys.stderr.write("Error: Blank passwords aren't allowed.\n") |
| 116 | self.stderr.write("Error: Blank passwords aren't allowed.") |
117 | 117 | password = None |
118 | 118 | continue |
119 | 119 | break |
120 | 120 | except KeyboardInterrupt: |
121 | | sys.stderr.write("\nOperation cancelled.\n") |
| 121 | self.stderr.write("\nOperation cancelled.") |
122 | 122 | sys.exit(1) |
123 | 123 | |
124 | 124 | User.objects.db_manager(database).create_superuser(username, email, password) |
125 | 125 | if verbosity >= 1: |
126 | | self.stdout.write("Superuser created successfully.\n") |
| 126 | self.stdout.write("Superuser created successfully.") |
127 | 127 | |
diff --git a/django/contrib/staticfiles/management/commands/collectstatic.py b/django/contrib/staticfiles/management/commands/collectstatic.py
index cab96c8..679eb81 100644
a
|
b
|
from optparse import make_option
|
4 | 4 | |
5 | 5 | from django.core.files.storage import FileSystemStorage |
6 | 6 | from django.core.management.base import CommandError, NoArgsCommand |
7 | | from django.utils.encoding import smart_str, smart_unicode |
| 7 | from django.utils.encoding import smart_unicode |
8 | 8 | from django.utils.datastructures import SortedDict |
9 | 9 | |
10 | 10 | from django.contrib.staticfiles import finders, storage |
… |
… |
Type 'yes' to continue, or 'no' to cancel: """
|
178 | 178 | ', %s post-processed' |
179 | 179 | % post_processed_count or ''), |
180 | 180 | } |
181 | | self.stdout.write(smart_str(summary)) |
| 181 | self.stdout.write(summary) |
182 | 182 | |
183 | 183 | def log(self, msg, level=2): |
184 | 184 | """ |
185 | 185 | Small log helper |
186 | 186 | """ |
187 | | msg = smart_str(msg) |
188 | 187 | if not msg.endswith("\n"): |
189 | 188 | msg += "\n" |
190 | 189 | if self.verbosity >= level: |
diff --git a/django/contrib/staticfiles/management/commands/findstatic.py b/django/contrib/staticfiles/management/commands/findstatic.py
index bcf0c2f..dc4406e 100644
a
|
b
|
class Command(LabelCommand):
|
23 | 23 | result = [result] |
24 | 24 | output = u'\n '.join( |
25 | 25 | (smart_unicode(os.path.realpath(path)) for path in result)) |
26 | | self.stdout.write( |
27 | | smart_str(u"Found '%s' here:\n %s\n" % (path, output))) |
| 26 | self.stdout.write(u"Found '%s' here:\n %s" % (path, output)) |
28 | 27 | else: |
29 | 28 | if verbosity >= 1: |
30 | | self.stderr.write( |
31 | | smart_str("No matching file found for '%s'.\n" % path)) |
| 29 | self.stderr.write("No matching file found for '%s'." % path) |
diff --git a/django/core/management/base.py b/django/core/management/base.py
index 121a5c6..16feb91 100644
a
|
b
|
def handle_default_options(options):
|
45 | 45 | sys.path.insert(0, options.pythonpath) |
46 | 46 | |
47 | 47 | |
| 48 | class OutputWrapper(object): |
| 49 | """ |
| 50 | Wrapper around stdout/stderr |
| 51 | """ |
| 52 | def __init__(self, out, style_func=None): |
| 53 | self._out = out |
| 54 | self.style_func = None |
| 55 | if hasattr(out, 'isatty') and out.isatty(): |
| 56 | self.style_func = style_func |
| 57 | |
| 58 | def __getattr__(self, name): |
| 59 | return getattr(self._out, name) |
| 60 | |
| 61 | def write(self, msg, style_func=None, ending='\n'): |
| 62 | if ending and not msg.endswith(ending): |
| 63 | msg += ending |
| 64 | if style_func is not None: |
| 65 | msg = style_func(msg) |
| 66 | elif self.style_func is not None: |
| 67 | msg = self.style_func(msg) |
| 68 | self._out.write(smart_str(msg)) |
| 69 | |
| 70 | |
48 | 71 | class BaseCommand(object): |
49 | 72 | """ |
50 | 73 | The base class from which all management commands ultimately |
… |
… |
class BaseCommand(object):
|
210 | 233 | # But only do this if we can assume we have a working settings file, |
211 | 234 | # because django.utils.translation requires settings. |
212 | 235 | saved_lang = None |
| 236 | self.stdout = OutputWrapper(options.get('stdout', sys.stdout)) |
| 237 | self.stderr = OutputWrapper(options.get('stderr', sys.stderr), self.style.ERROR) |
| 238 | |
213 | 239 | if self.can_import_settings: |
214 | 240 | try: |
215 | 241 | from django.utils import translation |
… |
… |
class BaseCommand(object):
|
221 | 247 | if show_traceback: |
222 | 248 | traceback.print_exc() |
223 | 249 | else: |
224 | | sys.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e))) |
| 250 | self.stderr.write('Error: %s' % e) |
225 | 251 | sys.exit(1) |
226 | 252 | |
227 | 253 | try: |
228 | | self.stdout = options.get('stdout', sys.stdout) |
229 | | self.stderr = options.get('stderr', sys.stderr) |
230 | 254 | if self.requires_model_validation and not options.get('skip_validation'): |
231 | 255 | self.validate() |
232 | 256 | output = self.handle(*args, **options) |
… |
… |
class BaseCommand(object):
|
237 | 261 | from django.db import connections, DEFAULT_DB_ALIAS |
238 | 262 | connection = connections[options.get('database', DEFAULT_DB_ALIAS)] |
239 | 263 | if connection.ops.start_transaction_sql(): |
240 | | self.stdout.write(self.style.SQL_KEYWORD(connection.ops.start_transaction_sql()) + '\n') |
| 264 | self.stdout.write(self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())) |
241 | 265 | self.stdout.write(output) |
242 | 266 | if self.output_transaction: |
243 | | self.stdout.write('\n' + self.style.SQL_KEYWORD("COMMIT;") + '\n') |
| 267 | self.stdout.write('\n' + self.style.SQL_KEYWORD("COMMIT;")) |
244 | 268 | except CommandError as e: |
245 | 269 | if show_traceback: |
246 | 270 | traceback.print_exc() |
247 | 271 | else: |
248 | | self.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e))) |
| 272 | self.stderr.write('Error: %s' % e) |
249 | 273 | sys.exit(1) |
250 | 274 | finally: |
251 | 275 | if saved_lang is not None: |
… |
… |
class BaseCommand(object):
|
266 | 290 | error_text = s.read() |
267 | 291 | raise CommandError("One or more models did not validate:\n%s" % error_text) |
268 | 292 | if display_num_errors: |
269 | | self.stdout.write("%s error%s found\n" % (num_errors, num_errors != 1 and 's' or '')) |
| 293 | self.stdout.write("%s error%s found" % (num_errors, num_errors != 1 and 's' or '')) |
270 | 294 | |
271 | 295 | def handle(self, *args, **options): |
272 | 296 | """ |
diff --git a/django/core/management/commands/createcachetable.py b/django/core/management/commands/createcachetable.py
index 82a126b..fec3aff 100644
a
|
b
|
class Command(LabelCommand):
|
56 | 56 | curs.execute("\n".join(full_statement)) |
57 | 57 | except DatabaseError as e: |
58 | 58 | self.stderr.write( |
59 | | self.style.ERROR("Cache table '%s' could not be created.\nThe error was: %s.\n" % |
60 | | (tablename, e))) |
| 59 | "Cache table '%s' could not be created.\nThe error was: %s." % |
| 60 | (tablename, e)) |
61 | 61 | transaction.rollback_unless_managed(using=db) |
62 | 62 | else: |
63 | 63 | for statement in index_output: |
diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py
index 71d6fa7..87b100b 100644
a
|
b
|
class Command(BaseCommand):
|
109 | 109 | objects.extend(model._default_manager.using(using).all()) |
110 | 110 | |
111 | 111 | try: |
112 | | return serializers.serialize(format, objects, indent=indent, |
113 | | use_natural_keys=use_natural_keys) |
| 112 | self.stdout.write(serializers.serialize(format, objects, |
| 113 | indent=indent, use_natural_keys=use_natural_keys), |
| 114 | ending='') |
114 | 115 | except Exception as e: |
115 | 116 | if show_traceback: |
116 | 117 | raise |
diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py
index 848b637..f44edf7 100644
a
|
b
|
class Command(BaseCommand):
|
34 | 34 | using = options.get('database') |
35 | 35 | |
36 | 36 | connection = connections[using] |
37 | | self.style = no_style() |
38 | 37 | |
39 | 38 | if not len(fixture_labels): |
40 | 39 | self.stderr.write( |
41 | | self.style.ERROR("No database fixture specified. Please provide the path of at least one fixture in the command line.\n") |
| 40 | "No database fixture specified. Please provide the path of at " |
| 41 | "least one fixture in the command line." |
42 | 42 | ) |
43 | 43 | return |
44 | 44 | |
… |
… |
class Command(BaseCommand):
|
124 | 124 | |
125 | 125 | if formats: |
126 | 126 | if verbosity >= 2: |
127 | | self.stdout.write("Loading '%s' fixtures...\n" % fixture_name) |
| 127 | self.stdout.write("Loading '%s' fixtures..." % fixture_name) |
128 | 128 | else: |
129 | 129 | self.stderr.write( |
130 | | self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format.\n" % |
131 | | (fixture_name, format))) |
| 130 | "Problem installing fixture '%s': %s is not a known serialization format." % |
| 131 | (fixture_name, format)) |
132 | 132 | if commit: |
133 | 133 | transaction.rollback(using=using) |
134 | 134 | transaction.leave_transaction_management(using=using) |
… |
… |
class Command(BaseCommand):
|
141 | 141 | |
142 | 142 | for fixture_dir in fixture_dirs: |
143 | 143 | if verbosity >= 2: |
144 | | self.stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir)) |
| 144 | self.stdout.write("Checking %s for fixtures..." % humanize(fixture_dir)) |
145 | 145 | |
146 | 146 | label_found = False |
147 | 147 | for combo in product([using, None], formats, compression_formats): |
… |
… |
class Command(BaseCommand):
|
154 | 154 | ) |
155 | 155 | |
156 | 156 | if verbosity >= 3: |
157 | | self.stdout.write("Trying %s for %s fixture '%s'...\n" % \ |
| 157 | self.stdout.write("Trying %s for %s fixture '%s'..." % \ |
158 | 158 | (humanize(fixture_dir), file_name, fixture_name)) |
159 | 159 | full_path = os.path.join(fixture_dir, file_name) |
160 | 160 | open_method = compression_types[compression_format] |
… |
… |
class Command(BaseCommand):
|
162 | 162 | fixture = open_method(full_path, 'r') |
163 | 163 | except IOError: |
164 | 164 | if verbosity >= 2: |
165 | | self.stdout.write("No %s fixture '%s' in %s.\n" % \ |
| 165 | self.stdout.write("No %s fixture '%s' in %s." % \ |
166 | 166 | (format, fixture_name, humanize(fixture_dir))) |
167 | 167 | else: |
168 | 168 | try: |
169 | 169 | if label_found: |
170 | | self.stderr.write(self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting.\n" % |
171 | | (fixture_name, humanize(fixture_dir)))) |
| 170 | self.stderr.write("Multiple fixtures named '%s' in %s. Aborting." % |
| 171 | (fixture_name, humanize(fixture_dir))) |
172 | 172 | if commit: |
173 | 173 | transaction.rollback(using=using) |
174 | 174 | transaction.leave_transaction_management(using=using) |
… |
… |
class Command(BaseCommand):
|
178 | 178 | objects_in_fixture = 0 |
179 | 179 | loaded_objects_in_fixture = 0 |
180 | 180 | if verbosity >= 2: |
181 | | self.stdout.write("Installing %s fixture '%s' from %s.\n" % \ |
| 181 | self.stdout.write("Installing %s fixture '%s' from %s." % \ |
182 | 182 | (format, fixture_name, humanize(fixture_dir))) |
183 | 183 | |
184 | 184 | objects = serializers.deserialize(format, fixture, using=using) |
… |
… |
class Command(BaseCommand):
|
209 | 209 | # error was encountered during fixture loading. |
210 | 210 | if objects_in_fixture == 0: |
211 | 211 | self.stderr.write( |
212 | | self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)\n" % |
213 | | (fixture_name))) |
| 212 | "No fixture data found for '%s'. (File format may be invalid.)" % |
| 213 | (fixture_name)) |
214 | 214 | if commit: |
215 | 215 | transaction.rollback(using=using) |
216 | 216 | transaction.leave_transaction_management(using=using) |
… |
… |
class Command(BaseCommand):
|
231 | 231 | traceback.print_exc() |
232 | 232 | else: |
233 | 233 | self.stderr.write( |
234 | | self.style.ERROR("Problem installing fixture '%s': %s\n" % |
| 234 | "Problem installing fixture '%s': %s" % |
235 | 235 | (full_path, ''.join(traceback.format_exception(sys.exc_type, |
236 | | sys.exc_value, sys.exc_traceback))))) |
| 236 | sys.exc_value, sys.exc_traceback)))) |
237 | 237 | return |
238 | 238 | |
239 | 239 | |
240 | 240 | # If we found even one object in a fixture, we need to reset the |
241 | 241 | # database sequences. |
242 | 242 | if loaded_object_count > 0: |
243 | | sequence_sql = connection.ops.sequence_reset_sql(self.style, models) |
| 243 | sequence_sql = connection.ops.sequence_reset_sql(no_style(), models) |
244 | 244 | if sequence_sql: |
245 | 245 | if verbosity >= 2: |
246 | 246 | self.stdout.write("Resetting sequences\n") |
… |
… |
class Command(BaseCommand):
|
253 | 253 | |
254 | 254 | if verbosity >= 1: |
255 | 255 | if fixture_object_count == loaded_object_count: |
256 | | self.stdout.write("Installed %d object(s) from %d fixture(s)\n" % ( |
| 256 | self.stdout.write("Installed %d object(s) from %d fixture(s)" % ( |
257 | 257 | loaded_object_count, fixture_count)) |
258 | 258 | else: |
259 | | self.stdout.write("Installed %d object(s) (of %d) from %d fixture(s)\n" % ( |
| 259 | self.stdout.write("Installed %d object(s) (of %d) from %d fixture(s)" % ( |
260 | 260 | loaded_object_count, fixture_object_count, fixture_count)) |
261 | 261 | |
262 | 262 | # Close the DB connection. This is required as a workaround for an |
diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py
index e618219..4f55854 100644
a
|
b
|
class Command(BaseCommand):
|
120 | 120 | error_text = ERRORS[e.args[0].args[0]] |
121 | 121 | except (AttributeError, KeyError): |
122 | 122 | error_text = str(e) |
123 | | sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n') |
| 123 | sys.stderr.write("Error: %s" % error_text) |
124 | 124 | # Need to use an OS exit because sys.exit doesn't work in a thread |
125 | 125 | os._exit(1) |
126 | 126 | except KeyboardInterrupt: |
127 | 127 | if shutdown_message: |
128 | | self.stdout.write("%s\n" % shutdown_message) |
| 128 | self.stdout.write("%s" % shutdown_message) |
129 | 129 | sys.exit(0) |
130 | 130 | |
131 | 131 | |
diff --git a/django/core/management/templates.py b/django/core/management/templates.py
index 735e29a..623aa69 100644
a
|
b
|
from os import path
|
16 | 16 | import django |
17 | 17 | from django.template import Template, Context |
18 | 18 | from django.utils import archive |
19 | | from django.utils.encoding import smart_str |
20 | 19 | from django.utils._os import rmtree_errorhandler |
21 | 20 | from django.core.management.base import BaseCommand, CommandError |
22 | 21 | from django.core.management.commands.makemessages import handle_extensions |
… |
… |
class TemplateCommand(BaseCommand):
|
166 | 165 | shutil.copymode(old_path, new_path) |
167 | 166 | self.make_writeable(new_path) |
168 | 167 | except OSError: |
169 | | notice = self.style.NOTICE( |
| 168 | self.stderr.write( |
170 | 169 | "Notice: Couldn't set permission bits on %s. You're " |
171 | 170 | "probably using an uncommon filesystem setup. No " |
172 | | "problem.\n" % new_path) |
173 | | sys.stderr.write(smart_str(notice)) |
| 171 | "problem." % new_path, self.style.NOTICE) |
174 | 172 | |
175 | 173 | if self.paths_to_remove: |
176 | 174 | if self.verbosity >= 2: |
diff --git a/tests/modeltests/user_commands/tests.py b/tests/modeltests/user_commands/tests.py
index 896dd66..c1e2bf9 100644
a
|
b
|
class CommandTests(TestCase):
|
11 | 11 | out = StringIO() |
12 | 12 | management.call_command('dance', stdout=out) |
13 | 13 | self.assertEqual(out.getvalue(), |
14 | | "I don't feel like dancing Rock'n'Roll.") |
| 14 | "I don't feel like dancing Rock'n'Roll.\n") |
15 | 15 | |
16 | 16 | def test_command_style(self): |
17 | 17 | out = StringIO() |
18 | 18 | management.call_command('dance', style='Jive', stdout=out) |
19 | 19 | self.assertEqual(out.getvalue(), |
20 | | "I don't feel like dancing Jive.") |
| 20 | "I don't feel like dancing Jive.\n") |
21 | 21 | |
22 | 22 | def test_language_preserved(self): |
23 | 23 | out = StringIO() |