Mikhail Korobov avatar Mikhail Korobov committed 7cd1ffa

Quote/unquote WEBTEST_USER wsgi environment variable. See GH-8.

Comments (0)

Files changed (5)

django_webtest/__init__.py

 from webtest import TestApp
 
 from django_webtest.response import DjangoWebtestResponse
-from django_webtest.compat import to_string
+from django_webtest.compat import to_string, to_wsgi_safe_string
 
 
 class DjangoTestApp(TestApp):
     def _update_environ(self, environ, user):
         if user:
             environ = environ or {}
-            if hasattr(user, 'get_username'):
-                # custom user, django 1.5+
-                environ['WEBTEST_USER'] = to_string(user.get_username())
-            elif hasattr(user, 'username'):
-                # standard User
-                environ['WEBTEST_USER'] = to_string(user.username)
-            else:
-                # username
-                environ['WEBTEST_USER'] = to_string(user)
+            username = _get_username(user)
+            environ['WEBTEST_USER'] = to_wsgi_safe_string(username)
         return environ
 
     def do_request(self, req, status, expect_errors):
                 return engine.SessionStore(cookie)
         return {}
 
+
 class WebTest(TestCase):
 
     extra_environ = {}
         res = super(WebTest, self).__call__(result)
         self._unpatch_settings()
         return res
+
+
+def _get_username(user):
+    """
+    Return user's username. ``user`` can be standard Django User
+    instance, a custom user model or just an username (as string).
+    """
+    if hasattr(user, 'get_username'):  # custom user, django 1.5+
+        return user.get_username()
+    elif hasattr(user, 'username'):    # standard User
+        return user.username
+    else:                              # assume user is just an username
+        return user
+

django_webtest/backends.py

+from __future__ import absolute_import
 from django.contrib.auth.backends import RemoteUserBackend
+from .compat import from_wsgi_safe_string
 
 class WebtestUserBackend(RemoteUserBackend):
     """ Auth backend for django-webtest auth system """
     def authenticate(self, django_webtest_user):
         return super(WebtestUserBackend, self).authenticate(django_webtest_user)
 
+    def clean_username(self, username):
+        return from_wsgi_safe_string(username)
+

django_webtest/compat.py

 import sys
+import urllib
 
 PY3 = sys.version_info[0] == 3
 
 if PY3:
+    from urllib import parse as urlparse
+
     def to_string(s):
         if isinstance(s, str):
             return s
         return str(s, 'latin1')
 
-    from urllib import parse as urlparse
+    def to_wsgi_safe_string(s):
+        return urlparse.quote(to_string(s))
+
+    def from_wsgi_safe_string(s):
+        return urlparse.unquote(s)
 
 else:
+    import urlparse
 
     def to_string(s):
         return str(s)
 
-    import urlparse
+    def to_wsgi_safe_string(s):
+        return to_string(urllib.quote(s.encode('utf8')))
 
+    def from_wsgi_safe_string(s):
+        return urllib.unquote(s).decode('utf8')
+
+
+

django_webtest_tests/testapp_tests/tests.py

         form['password'] = password
         return form.submit()
 
+    def assertCanLogin(self, user):
+        response = self.app.get('/template/index.html', user=user)
+        res_user = response.context['user']
+        assert res_user.is_authenticated()
+
+        if isinstance(user, User):
+            self.assertEqual(res_user, user)
+        else:
+            self.assertEqual(res_user.username, user)
+
 
 class AuthTest(BaseAuthTest):
 
         assert not user.is_authenticated()
 
     def test_logged_using_username(self):
-        response = self.app.get('/template/index.html', user='foo')
-        user = response.context['user']
-        assert user.is_authenticated()
-        self.assertEqual(user, self.user)
+        self.assertCanLogin('foo')
+
+    def test_logged_using_native_username(self):
+        self.assertCanLogin(str('foo'))
+
+    def test_logged_using_unicode_username(self):
+        self.assertCanLogin('ƒøø')
 
     def test_logged_using_instance(self):
-        response = self.app.get('/template/index.html', user=self.user)
-        user = response.context['user']
-        assert user.is_authenticated()
-        self.assertEqual(user, self.user)
+        self.assertCanLogin(self.user)
+
+    def test_logged_using_unicode_instance(self):
+        user = User.objects.create_user('ƒøø', 'example@example.com', '123')
+        self.assertCanLogin(user)
 
     def test_auth_is_enabled(self):
         from django.conf import settings
 [testenv:py26]
 basepython = python2.6
 
+[testenv:py32]
+basepython = python3.2
+
+[testenv:py33]
+basepython = python3.3
+
 [testenv:pypy]
 basepython = pypy
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.