From 55c585f1c7a9c91308193f0648caf36203174564 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Mon, 4 Feb 2013 10:04:56 +0100 Subject: [PATCH] Fixed #19725 -- Made createsuperuser handle non-ascii prompts Thanks Michisu for the report. --- .../management/commands/createsuperuser.py | 8 ++- django/contrib/auth/tests/basic.py | 70 +++++++++++++++---- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/django/contrib/auth/management/commands/createsuperuser.py b/django/contrib/auth/management/commands/createsuperuser.py index 7b4764abc3..4169da248c 100644 --- a/django/contrib/auth/management/commands/createsuperuser.py +++ b/django/contrib/auth/management/commands/createsuperuser.py @@ -11,6 +11,7 @@ from django.contrib.auth.management import get_default_username from django.core import exceptions from django.core.management.base import BaseCommand, CommandError from django.db import DEFAULT_DB_ALIAS +from django.utils.encoding import force_str from django.utils.six.moves import input from django.utils.text import capfirst @@ -83,8 +84,9 @@ class Command(BaseCommand): if not username: input_msg = capfirst(self.username_field.verbose_name) if default_username: - input_msg += " (leave blank to use '%s')" % default_username - raw_value = input(input_msg + ': ') + input_msg = "%s (leave blank to use '%s')" % ( + input_msg, default_username) + raw_value = input(force_str('%s: ' % input_msg)) if default_username and raw_value == '': raw_value = default_username @@ -107,7 +109,7 @@ class Command(BaseCommand): field = self.UserModel._meta.get_field(field_name) user_data[field_name] = options.get(field_name) while user_data[field_name] is None: - raw_value = input(capfirst(field.verbose_name + ': ')) + raw_value = input(force_str('%s: ' % capfirst(field.verbose_name))) try: user_data[field_name] = field.clean(raw_value, None) except exceptions.ValidationError as e: diff --git a/django/contrib/auth/tests/basic.py b/django/contrib/auth/tests/basic.py index 2c807cca51..8627329870 100644 --- a/django/contrib/auth/tests/basic.py +++ b/django/contrib/auth/tests/basic.py @@ -1,3 +1,6 @@ +# -*- encoding: utf-8 -*- +from __future__ import unicode_literals + import locale from django.contrib.auth import get_user_model @@ -12,6 +15,37 @@ from django.test.utils import override_settings from django.utils.six import StringIO +def mock_inputs(inputs): + """ + Decorator to temporarily replace input/getpass to allow interactive + createsuperuser. + """ + def inner(test_func): + def wrapped(*args): + class mock_getpass: + pass + mock_getpass.getpass = staticmethod(lambda p=None: inputs['password']) + + def mock_input(prompt): + # prompt should be encoded in Python 2. This line will raise an + # Exception if prompt contains unencoded non-ascii on Python 2. + prompt = str(prompt) + if str('leave blank to use') in prompt: + return inputs['username'] + + old_getpass = createsuperuser.getpass + old_input = createsuperuser.input + createsuperuser.getpass = mock_getpass + createsuperuser.input = mock_input + try: + test_func(*args) + finally: + createsuperuser.getpass = old_getpass + createsuperuser.input = old_input + return wrapped + return inner + + @skipIfCustomUser class BasicTestCase(TestCase): def test_user(self): @@ -103,17 +137,17 @@ class BasicTestCase(TestCase): self.assertEqual(u.email, 'joe2@somewhere.org') self.assertFalse(u.has_usable_password()) - new_io = StringIO() call_command("createsuperuser", interactive=False, username="joe+admin@somewhere.org", email="joe@somewhere.org", - stdout=new_io + verbosity=0 ) u = User.objects.get(username="joe+admin@somewhere.org") self.assertEqual(u.email, 'joe@somewhere.org') self.assertFalse(u.has_usable_password()) + @mock_inputs({'password': "nopasswd"}) def test_createsuperuser_nolocale(self): """ Check that createsuperuser does not break when no locale is set. See @@ -121,39 +155,47 @@ class BasicTestCase(TestCase): """ old_getdefaultlocale = locale.getdefaultlocale - old_getpass = createsuperuser.getpass try: # Temporarily remove locale information locale.getdefaultlocale = lambda: (None, None) - # Temporarily replace getpass to allow interactive code to be used - # non-interactively - class mock_getpass: - pass - mock_getpass.getpass = staticmethod(lambda p=None: "nopasswd") - createsuperuser.getpass = mock_getpass - # Call the command in this new environment - new_io = StringIO() call_command("createsuperuser", interactive=True, username="nolocale@somewhere.org", email="nolocale@somewhere.org", - stdout=new_io + verbosity=0 ) except TypeError: self.fail("createsuperuser fails if the OS provides no information about the current locale") finally: - # Re-apply locale and getpass information - createsuperuser.getpass = old_getpass + # Re-apply locale information locale.getdefaultlocale = old_getdefaultlocale # If we were successful, a user should have been created u = User.objects.get(username="nolocale@somewhere.org") self.assertEqual(u.email, 'nolocale@somewhere.org') + @mock_inputs({'password': "nopasswd", 'username': 'foo'}) + def test_createsuperuser_non_ascii_verbose_name(self): + username_field = User._meta.get_field('username') + old_verbose_name = username_field.verbose_name + username_field.verbose_name = 'uživatel' + new_io = StringIO() + try: + call_command("createsuperuser", + interactive=True, + email="nolocale@somewhere.org", + stdout=new_io + ) + finally: + username_field.verbose_name = old_verbose_name + + command_output = new_io.getvalue().strip() + self.assertEqual(command_output, 'Superuser created successfully.') + def test_get_user_model(self): "The current user model can be retrieved" self.assertEqual(get_user_model(), User)