Skip to content

Commit

Permalink
Fixed #19725 -- Made createsuperuser handle non-ascii prompts
Browse files Browse the repository at this point in the history
Thanks Michisu for the report.
  • Loading branch information
claudep committed Feb 4, 2013
1 parent fb606e1 commit 55c585f
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 17 deletions.
8 changes: 5 additions & 3 deletions django/contrib/auth/management/commands/createsuperuser.py
Expand Up @@ -11,6 +11,7 @@
from django.core import exceptions from django.core import exceptions
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.db import DEFAULT_DB_ALIAS from django.db import DEFAULT_DB_ALIAS
from django.utils.encoding import force_str
from django.utils.six.moves import input from django.utils.six.moves import input
from django.utils.text import capfirst from django.utils.text import capfirst


Expand Down Expand Up @@ -83,8 +84,9 @@ def handle(self, *args, **options):
if not username: if not username:
input_msg = capfirst(self.username_field.verbose_name) input_msg = capfirst(self.username_field.verbose_name)
if default_username: if default_username:
input_msg += " (leave blank to use '%s')" % default_username input_msg = "%s (leave blank to use '%s')" % (
raw_value = input(input_msg + ': ') input_msg, default_username)
raw_value = input(force_str('%s: ' % input_msg))


if default_username and raw_value == '': if default_username and raw_value == '':
raw_value = default_username raw_value = default_username
Expand All @@ -107,7 +109,7 @@ def handle(self, *args, **options):
field = self.UserModel._meta.get_field(field_name) field = self.UserModel._meta.get_field(field_name)
user_data[field_name] = options.get(field_name) user_data[field_name] = options.get(field_name)
while user_data[field_name] is None: 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: try:
user_data[field_name] = field.clean(raw_value, None) user_data[field_name] = field.clean(raw_value, None)
except exceptions.ValidationError as e: except exceptions.ValidationError as e:
Expand Down
70 changes: 56 additions & 14 deletions django/contrib/auth/tests/basic.py
@@ -1,3 +1,6 @@
# -*- encoding: utf-8 -*-
from __future__ import unicode_literals

import locale import locale


from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
Expand All @@ -12,6 +15,37 @@
from django.utils.six import StringIO 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 @skipIfCustomUser
class BasicTestCase(TestCase): class BasicTestCase(TestCase):
def test_user(self): def test_user(self):
Expand Down Expand Up @@ -103,57 +137,65 @@ def test_createsuperuser_management_command(self):
self.assertEqual(u.email, 'joe2@somewhere.org') self.assertEqual(u.email, 'joe2@somewhere.org')
self.assertFalse(u.has_usable_password()) self.assertFalse(u.has_usable_password())


new_io = StringIO()
call_command("createsuperuser", call_command("createsuperuser",
interactive=False, interactive=False,
username="joe+admin@somewhere.org", username="joe+admin@somewhere.org",
email="joe@somewhere.org", email="joe@somewhere.org",
stdout=new_io verbosity=0
) )
u = User.objects.get(username="joe+admin@somewhere.org") u = User.objects.get(username="joe+admin@somewhere.org")
self.assertEqual(u.email, 'joe@somewhere.org') self.assertEqual(u.email, 'joe@somewhere.org')
self.assertFalse(u.has_usable_password()) self.assertFalse(u.has_usable_password())


@mock_inputs({'password': "nopasswd"})
def test_createsuperuser_nolocale(self): def test_createsuperuser_nolocale(self):
""" """
Check that createsuperuser does not break when no locale is set. See Check that createsuperuser does not break when no locale is set. See
ticket #16017. ticket #16017.
""" """


old_getdefaultlocale = locale.getdefaultlocale old_getdefaultlocale = locale.getdefaultlocale
old_getpass = createsuperuser.getpass
try: try:
# Temporarily remove locale information # Temporarily remove locale information
locale.getdefaultlocale = lambda: (None, None) 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 # Call the command in this new environment
new_io = StringIO()
call_command("createsuperuser", call_command("createsuperuser",
interactive=True, interactive=True,
username="nolocale@somewhere.org", username="nolocale@somewhere.org",
email="nolocale@somewhere.org", email="nolocale@somewhere.org",
stdout=new_io verbosity=0
) )


except TypeError: except TypeError:
self.fail("createsuperuser fails if the OS provides no information about the current locale") self.fail("createsuperuser fails if the OS provides no information about the current locale")


finally: finally:
# Re-apply locale and getpass information # Re-apply locale information
createsuperuser.getpass = old_getpass
locale.getdefaultlocale = old_getdefaultlocale locale.getdefaultlocale = old_getdefaultlocale


# If we were successful, a user should have been created # If we were successful, a user should have been created
u = User.objects.get(username="nolocale@somewhere.org") u = User.objects.get(username="nolocale@somewhere.org")
self.assertEqual(u.email, '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): def test_get_user_model(self):
"The current user model can be retrieved" "The current user model can be retrieved"
self.assertEqual(get_user_model(), User) self.assertEqual(get_user_model(), User)
Expand Down

0 comments on commit 55c585f

Please sign in to comment.