Ticket #18325: 18325.diff

File 18325.diff, 20.1 KB (added by Claude Paroz, 12 years ago)

Wrap self.stdout/selfstderr in OutputWrapper

  • django/contrib/auth/management/commands/createsuperuser.py

    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):  
    8080                    if default_username and username == '':
    8181                        username = default_username
    8282                    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.")
    8484                        username = None
    8585                        continue
    8686                    try:
    class Command(BaseCommand):  
    8888                    except User.DoesNotExist:
    8989                        break
    9090                    else:
    91                         sys.stderr.write("Error: That username is already taken.\n")
     91                        self.stderr.write("Error: That username is already taken.")
    9292                        username = None
    9393
    9494                # Get an email
    class Command(BaseCommand):  
    9898                    try:
    9999                        is_valid_email(email)
    100100                    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.")
    102102                        email = None
    103103                    else:
    104104                        break
    class Command(BaseCommand):  
    109109                        password = getpass.getpass()
    110110                        password2 = getpass.getpass('Password (again): ')
    111111                        if password != password2:
    112                             sys.stderr.write("Error: Your passwords didn't match.\n")
     112                            self.stderr.write("Error: Your passwords didn't match.")
    113113                            password = None
    114114                            continue
    115115                    if password.strip() == '':
    116                         sys.stderr.write("Error: Blank passwords aren't allowed.\n")
     116                        self.stderr.write("Error: Blank passwords aren't allowed.")
    117117                        password = None
    118118                        continue
    119119                    break
    120120            except KeyboardInterrupt:
    121                 sys.stderr.write("\nOperation cancelled.\n")
     121                self.stderr.write("\nOperation cancelled.")
    122122                sys.exit(1)
    123123
    124124        User.objects.db_manager(database).create_superuser(username, email, password)
    125125        if verbosity >= 1:
    126           self.stdout.write("Superuser created successfully.\n")
     126          self.stdout.write("Superuser created successfully.")
    127127
  • django/contrib/staticfiles/management/commands/collectstatic.py

    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  
    44
    55from django.core.files.storage import FileSystemStorage
    66from django.core.management.base import CommandError, NoArgsCommand
    7 from django.utils.encoding import smart_str, smart_unicode
     7from django.utils.encoding import smart_unicode
    88from django.utils.datastructures import SortedDict
    99
    1010from django.contrib.staticfiles import finders, storage
    Type 'yes' to continue, or 'no' to cancel: """  
    178178                                   ', %s post-processed'
    179179                                   % post_processed_count or ''),
    180180            }
    181             self.stdout.write(smart_str(summary))
     181            self.stdout.write(summary)
    182182
    183183    def log(self, msg, level=2):
    184184        """
    185185        Small log helper
    186186        """
    187         msg = smart_str(msg)
    188187        if not msg.endswith("\n"):
    189188            msg += "\n"
    190189        if self.verbosity >= level:
  • django/contrib/staticfiles/management/commands/findstatic.py

    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):  
    2323                result = [result]
    2424            output = u'\n  '.join(
    2525                (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))
    2827        else:
    2928            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)
  • django/core/management/base.py

    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):  
    4545        sys.path.insert(0, options.pythonpath)
    4646
    4747
     48class 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
    4871class BaseCommand(object):
    4972    """
    5073    The base class from which all management commands ultimately
    class BaseCommand(object):  
    210233        # But only do this if we can assume we have a working settings file,
    211234        # because django.utils.translation requires settings.
    212235        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
    213239        if self.can_import_settings:
    214240            try:
    215241                from django.utils import translation
    class BaseCommand(object):  
    221247                if show_traceback:
    222248                    traceback.print_exc()
    223249                else:
    224                     sys.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e)))
     250                    self.stderr.write('Error: %s' % e)
    225251                sys.exit(1)
    226252
    227253        try:
    228             self.stdout = options.get('stdout', sys.stdout)
    229             self.stderr = options.get('stderr', sys.stderr)
    230254            if self.requires_model_validation and not options.get('skip_validation'):
    231255                self.validate()
    232256            output = self.handle(*args, **options)
    class BaseCommand(object):  
    237261                    from django.db import connections, DEFAULT_DB_ALIAS
    238262                    connection = connections[options.get('database', DEFAULT_DB_ALIAS)]
    239263                    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()))
    241265                self.stdout.write(output)
    242266                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;"))
    244268        except CommandError as e:
    245269            if show_traceback:
    246270                traceback.print_exc()
    247271            else:
    248                 self.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e)))
     272                self.stderr.write('Error: %s' % e)
    249273            sys.exit(1)
    250274        finally:
    251275            if saved_lang is not None:
    class BaseCommand(object):  
    266290            error_text = s.read()
    267291            raise CommandError("One or more models did not validate:\n%s" % error_text)
    268292        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 ''))
    270294
    271295    def handle(self, *args, **options):
    272296        """
  • django/core/management/commands/createcachetable.py

    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):  
    5656            curs.execute("\n".join(full_statement))
    5757        except DatabaseError as e:
    5858            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))
    6161            transaction.rollback_unless_managed(using=db)
    6262        else:
    6363            for statement in index_output:
  • django/core/management/commands/dumpdata.py

    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):  
    109109                    objects.extend(model._default_manager.using(using).all())
    110110
    111111        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='')
    114115        except Exception as e:
    115116            if show_traceback:
    116117                raise
  • django/core/management/commands/loaddata.py

    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):  
    3434        using = options.get('database')
    3535
    3636        connection = connections[using]
    37         self.style = no_style()
    3837
    3938        if not len(fixture_labels):
    4039            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."
    4242            )
    4343            return
    4444
    class Command(BaseCommand):  
    124124
    125125                    if formats:
    126126                        if verbosity >= 2:
    127                             self.stdout.write("Loading '%s' fixtures...\n" % fixture_name)
     127                            self.stdout.write("Loading '%s' fixtures..." % fixture_name)
    128128                    else:
    129129                        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))
    132132                        if commit:
    133133                            transaction.rollback(using=using)
    134134                            transaction.leave_transaction_management(using=using)
    class Command(BaseCommand):  
    141141
    142142                    for fixture_dir in fixture_dirs:
    143143                        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))
    145145
    146146                        label_found = False
    147147                        for combo in product([using, None], formats, compression_formats):
    class Command(BaseCommand):  
    154154                            )
    155155
    156156                            if verbosity >= 3:
    157                                 self.stdout.write("Trying %s for %s fixture '%s'...\n" % \
     157                                self.stdout.write("Trying %s for %s fixture '%s'..." % \
    158158                                    (humanize(fixture_dir), file_name, fixture_name))
    159159                            full_path = os.path.join(fixture_dir, file_name)
    160160                            open_method = compression_types[compression_format]
    class Command(BaseCommand):  
    162162                                fixture = open_method(full_path, 'r')
    163163                            except IOError:
    164164                                if verbosity >= 2:
    165                                     self.stdout.write("No %s fixture '%s' in %s.\n" % \
     165                                    self.stdout.write("No %s fixture '%s' in %s." % \
    166166                                        (format, fixture_name, humanize(fixture_dir)))
    167167                            else:
    168168                                try:
    169169                                    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)))
    172172                                        if commit:
    173173                                            transaction.rollback(using=using)
    174174                                            transaction.leave_transaction_management(using=using)
    class Command(BaseCommand):  
    178178                                    objects_in_fixture = 0
    179179                                    loaded_objects_in_fixture = 0
    180180                                    if verbosity >= 2:
    181                                         self.stdout.write("Installing %s fixture '%s' from %s.\n" % \
     181                                        self.stdout.write("Installing %s fixture '%s' from %s." % \
    182182                                            (format, fixture_name, humanize(fixture_dir)))
    183183
    184184                                    objects = serializers.deserialize(format, fixture, using=using)
    class Command(BaseCommand):  
    209209                                # error was encountered during fixture loading.
    210210                                if objects_in_fixture == 0:
    211211                                    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))
    214214                                    if commit:
    215215                                        transaction.rollback(using=using)
    216216                                        transaction.leave_transaction_management(using=using)
    class Command(BaseCommand):  
    231231                traceback.print_exc()
    232232            else:
    233233                self.stderr.write(
    234                     self.style.ERROR("Problem installing fixture '%s': %s\n" %
     234                    "Problem installing fixture '%s': %s" %
    235235                         (full_path, ''.join(traceback.format_exception(sys.exc_type,
    236                              sys.exc_value, sys.exc_traceback)))))
     236                             sys.exc_value, sys.exc_traceback))))
    237237            return
    238238
    239239
    240240        # If we found even one object in a fixture, we need to reset the
    241241        # database sequences.
    242242        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)
    244244            if sequence_sql:
    245245                if verbosity >= 2:
    246246                    self.stdout.write("Resetting sequences\n")
    class Command(BaseCommand):  
    253253
    254254        if verbosity >= 1:
    255255            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)" % (
    257257                    loaded_object_count, fixture_count))
    258258            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)" % (
    260260                    loaded_object_count, fixture_object_count, fixture_count))
    261261
    262262        # Close the DB connection. This is required as a workaround for an
  • django/core/management/commands/runserver.py

    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):  
    120120                error_text = ERRORS[e.args[0].args[0]]
    121121            except (AttributeError, KeyError):
    122122                error_text = str(e)
    123             sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
     123            sys.stderr.write("Error: %s" % error_text)
    124124            # Need to use an OS exit because sys.exit doesn't work in a thread
    125125            os._exit(1)
    126126        except KeyboardInterrupt:
    127127            if shutdown_message:
    128                 self.stdout.write("%s\n" % shutdown_message)
     128                self.stdout.write("%s" % shutdown_message)
    129129            sys.exit(0)
    130130
    131131
  • django/core/management/templates.py

    diff --git a/django/core/management/templates.py b/django/core/management/templates.py
    index 735e29a..623aa69 100644
    a b from os import path  
    1616import django
    1717from django.template import Template, Context
    1818from django.utils import archive
    19 from django.utils.encoding import smart_str
    2019from django.utils._os import rmtree_errorhandler
    2120from django.core.management.base import BaseCommand, CommandError
    2221from django.core.management.commands.makemessages import handle_extensions
    class TemplateCommand(BaseCommand):  
    166165                    shutil.copymode(old_path, new_path)
    167166                    self.make_writeable(new_path)
    168167                except OSError:
    169                     notice = self.style.NOTICE(
     168                    self.stderr.write(
    170169                        "Notice: Couldn't set permission bits on %s. You're "
    171170                        "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)
    174172
    175173        if self.paths_to_remove:
    176174            if self.verbosity >= 2:
  • tests/modeltests/user_commands/tests.py

    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):  
    1111        out = StringIO()
    1212        management.call_command('dance', stdout=out)
    1313        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")
    1515
    1616    def test_command_style(self):
    1717        out = StringIO()
    1818        management.call_command('dance', style='Jive', stdout=out)
    1919        self.assertEqual(out.getvalue(),
    20             "I don't feel like dancing Jive.")
     20            "I don't feel like dancing Jive.\n")
    2121
    2222    def test_language_preserved(self):
    2323        out = StringIO()
Back to Top