Commit 55c585f1 authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #19725 -- Made createsuperuser handle non-ascii prompts

Thanks Michisu for the report.
parent fb606e10
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -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:
+56 −14
Original line number Diff line number Diff line
# -*- 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)