Author: SmileyChris
Date: 2011-05-08 18:10:40 -0700 (Sun, 08 May 2011)
New Revision: 16182

Added:
   django/trunk/django/contrib/auth/tests/management.py
Modified:
   django/trunk/django/contrib/auth/management/__init__.py
   django/trunk/django/contrib/auth/management/commands/createsuperuser.py
   django/trunk/django/contrib/auth/tests/__init__.py
Log:
Fixes #15778 -- createsuperuser fails on international characters in system 
user names. Thanks for the patch, Hynek Cernoch.

Modified: django/trunk/django/contrib/auth/management/__init__.py
===================================================================
--- django/trunk/django/contrib/auth/management/__init__.py     2011-05-07 
19:55:51 UTC (rev 16181)
+++ django/trunk/django/contrib/auth/management/__init__.py     2011-05-09 
01:10:40 UTC (rev 16182)
@@ -1,14 +1,18 @@
 """
 Creates permissions for all installed apps that need permissions.
 """
-
+import getpass
+import locale
+import unicodedata
 from django.contrib.auth import models as auth_app
 from django.db.models import get_models, signals
+from django.contrib.auth.models import User
 
 
 def _get_permission_codename(action, opts):
     return u'%s_%s' % (action, opts.object_name.lower())
 
+
 def _get_all_permissions(opts):
     "Returns (codename, name) for all permissions in the given opts."
     perms = []
@@ -16,6 +20,7 @@
         perms.append((_get_permission_codename(action, opts), u'Can %s %s' % 
(action, opts.verbose_name_raw)))
     return perms + list(opts.permissions)
 
+
 def create_permissions(app, created_models, verbosity, **kwargs):
     from django.contrib.contenttypes.models import ContentType
 
@@ -70,6 +75,54 @@
                 call_command("createsuperuser", interactive=True)
             break
 
+
+def get_system_username():
+    """
+    Try to determine the current system user's username.
+
+    :returns: The username as a unicode string, or an empty string if the
+        username could not be determined.
+    """
+    try:
+        return getpass.getuser().decode(locale.getdefaultlocale()[1])
+    except (ImportError, KeyError, UnicodeDecodeError):
+        # KeyError will be raised by os.getpwuid() (called by getuser())
+        # if there is no corresponding entry in the /etc/passwd file
+        # (a very restricted chroot environment, for example).
+        # UnicodeDecodeError - preventive treatment for non-latin Windows.
+        return u''
+
+
+def get_default_username(check_db=True):
+    """
+    Try to determine the current system user's username to use as a default.
+
+    :param check_db: If ``True``, requires that the username does not match an
+        existing ``auth.User`` (otherwise returns an empty string).
+    :returns: The username, or an empty string if no username can be
+        determined.
+    """
+    from django.contrib.auth.management.commands.createsuperuser import \
+        RE_VALID_USERNAME
+    default_username = get_system_username()
+    try:
+        default_username = unicodedata.normalize('NFKD', default_username)\
+            .encode('ascii', 'ignore').replace(' ', '').lower()
+    except UnicodeDecodeError:
+        return ''
+    if not RE_VALID_USERNAME.match(default_username):
+        return ''
+    # Don't return the default username if it is already taken.
+    if check_db and default_username:
+        try:
+            User.objects.get(username=default_username)
+        except User.DoesNotExist:
+            pass
+        else:
+            return ''
+    return default_username
+
+
 signals.post_syncdb.connect(create_permissions,
     dispatch_uid = "django.contrib.auth.management.create_permissions")
 signals.post_syncdb.connect(create_superuser,

Modified: 
django/trunk/django/contrib/auth/management/commands/createsuperuser.py
===================================================================
--- django/trunk/django/contrib/auth/management/commands/createsuperuser.py     
2011-05-07 19:55:51 UTC (rev 16181)
+++ django/trunk/django/contrib/auth/management/commands/createsuperuser.py     
2011-05-09 01:10:40 UTC (rev 16182)
@@ -7,6 +7,7 @@
 import sys
 from optparse import make_option
 from django.contrib.auth.models import User
+from django.contrib.auth.management import get_default_username
 from django.core import exceptions
 from django.core.management.base import BaseCommand, CommandError
 from django.utils.translation import ugettext as _
@@ -56,28 +57,10 @@
         # If not provided, create the user with an unusable password
         password = None
 
-        # Try to determine the current system user's username to use as a 
default.
-        try:
-            default_username = getpass.getuser().replace(' ', '').lower()
-        except (ImportError, KeyError):
-            # KeyError will be raised by os.getpwuid() (called by getuser())
-            # if there is no corresponding entry in the /etc/passwd file
-            # (a very restricted chroot environment, for example).
-            default_username = ''
-
-        # Determine whether the default username is taken, so we don't display
-        # it as an option.
-        if default_username:
-            try:
-                User.objects.get(username=default_username)
-            except User.DoesNotExist:
-                pass
-            else:
-                default_username = ''
-
         # Prompt for username/email/password. Enclose this whole thing in a
         # try/except to trap for a keyboard interrupt and exit gracefully.
         if interactive:
+            default_username = get_default_username()
             try:
 
                 # Get a username

Modified: django/trunk/django/contrib/auth/tests/__init__.py
===================================================================
--- django/trunk/django/contrib/auth/tests/__init__.py  2011-05-07 19:55:51 UTC 
(rev 16181)
+++ django/trunk/django/contrib/auth/tests/__init__.py  2011-05-09 01:10:40 UTC 
(rev 16182)
@@ -8,6 +8,7 @@
     UserChangeFormTest, PasswordResetFormTest)
 from django.contrib.auth.tests.remote_user import (RemoteUserTest,
     RemoteUserNoCreateTest, RemoteUserCustomTest)
+from django.contrib.auth.tests.management import GetDefaultUsernameTestCase
 from django.contrib.auth.tests.models import ProfileTestCase
 from django.contrib.auth.tests.signals import SignalTestCase
 from django.contrib.auth.tests.tokens import TokenGeneratorTest

Added: django/trunk/django/contrib/auth/tests/management.py
===================================================================
--- django/trunk/django/contrib/auth/tests/management.py                        
        (rev 0)
+++ django/trunk/django/contrib/auth/tests/management.py        2011-05-09 
01:10:40 UTC (rev 16182)
@@ -0,0 +1,27 @@
+from django.test import TestCase
+from django.contrib.auth import models, management
+
+
+class GetDefaultUsernameTestCase(TestCase):
+
+    def setUp(self):
+        self._getpass_getuser = management.get_system_username
+
+    def tearDown(self):
+        management.get_system_username = self._getpass_getuser
+
+    def test_simple(self):
+        management.get_system_username = lambda: u'joe'
+        self.assertEqual(management.get_default_username(), 'joe')
+
+    def test_existing(self):
+        models.User.objects.create(username='joe')
+        management.get_system_username = lambda: u'joe'
+        self.assertEqual(management.get_default_username(), '')
+        self.assertEqual(
+            management.get_default_username(check_db=False), 'joe')
+
+    def test_i18n(self):
+        # 'Julia' with accented 'u':
+        management.get_system_username = lambda: u'J\xfalia'
+        self.assertEqual(management.get_default_username(), 'julia')

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to