Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes to failing tests in Django 1.4 on AppEngine #1

Open
wants to merge 4 commits into
base: 1.4-nonrel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }}

Expand Down
4 changes: 2 additions & 2 deletions django/contrib/auth/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.forms.util import flatatt
from django.template import loader
from django.utils.encoding import smart_str
from django.utils.http import int_to_base36
from django.utils.http import urlsafe_base64_encode
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext, ugettext_lazy as _

Expand Down Expand Up @@ -230,7 +230,7 @@ def save(self, domain_override=None,
'email': user.email,
'domain': domain,
'site_name': site_name,
'uid': int_to_base36(user.id),
'uid': urlsafe_base64_encode(str(user.id)),
'user': user,
'token': token_generator.make_token(user),
'protocol': use_https and 'https' or 'http',
Expand Down
7 changes: 3 additions & 4 deletions django/contrib/auth/management/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ def create_permissions(app, created_models, verbosity, **kwargs):
# Find all the Permissions that have a context_type for a model we're
# looking for. We don't need to check for codenames since we already have
# a list of the ones we're going to create.

ctypes_pks = set(ct.pk for ct in ctypes)
all_perms = set(auth_app.Permission.objects.filter(
content_type__in=ctypes,
).values_list(
"content_type", "codename"
))
content_type__in=ctypes_pks).values_list('content_type', 'codename')[:1000000])

objs = [
auth_app.Permission(codename=codename, name=name, content_type=ctype)
Expand Down
3 changes: 1 addition & 2 deletions django/contrib/auth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ class Meta:
verbose_name = _('permission')
verbose_name_plural = _('permissions')
unique_together = (('content_type', 'codename'),)
ordering = ('content_type__app_label', 'content_type__model',
'codename')
ordering = ('codename',)

def __unicode__(self):
return u"%s | %s | %s" % (
Expand Down
7 changes: 7 additions & 0 deletions django/contrib/auth/tests/auth_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
from django.contrib.auth.models import User, Group, Permission, AnonymousUser
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured
from django.db import connection
from django.test import TestCase
from django.utils import unittest


class BackendTest(TestCase):
Expand Down Expand Up @@ -98,6 +100,9 @@ def test_get_all_superuser_permissions(self):
user = User.objects.get(username='test2')
self.assertEqual(len(user.get_all_permissions()), len(Permission.objects.all()))

BackendTest = unittest.skipIf(not connection.features.supports_joins,
'Requires JOIN support')(BackendTest)

class TestObj(object):
pass

Expand Down Expand Up @@ -194,6 +199,8 @@ def test_get_group_permissions(self):
self.user3.groups.add(group)
self.assertEqual(self.user3.get_group_permissions(TestObj()), set(['group_perm']))

RowlevelBackendTest = unittest.skipIf(not connection.features.supports_joins,
'Requires JOIN support')(RowlevelBackendTest)

class AnonymousUserBackend(SimpleRowlevelBackend):
supports_inactive_user = False
Expand Down
8 changes: 6 additions & 2 deletions django/contrib/auth/tests/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from django.test import TestCase
from django.test.utils import override_settings
from django.utils.encoding import force_unicode
from django.utils import translation
from django.utils import translation, unittest
from django.utils.translation import ugettext as _

from django.db import router, connections

class UserCreationFormTest(TestCase):

Expand Down Expand Up @@ -213,6 +213,7 @@ class UserChangeFormTest(TestCase):

fixtures = ['authtestdata.json']

@unittest.skipIf(not connections[router.db_for_read(User)].features.supports_joins, 'Requires JOIN support')
def test_username_validity(self):
user = User.objects.get(username='testclient')
data = {'username': 'not valid'}
Expand All @@ -236,18 +237,21 @@ class Meta(UserChangeForm.Meta):
# Just check we can create it
form = MyUserForm({})

@unittest.skipIf(not connections[router.db_for_read(User)].features.supports_joins, 'Requires JOIN support')
def test_bug_17944_empty_password(self):
user = User.objects.get(username='empty_password')
form = UserChangeForm(instance=user)
# Just check that no error is raised.
form.as_table()

@unittest.skipIf(not connections[router.db_for_read(User)].features.supports_joins, 'Requires JOIN support')
def test_bug_17944_unmanageable_password(self):
user = User.objects.get(username='unmanageable_password')
form = UserChangeForm(instance=user)
# Just check that no error is raised.
form.as_table()

@unittest.skipIf(not connections[router.db_for_read(User)].features.supports_joins, 'Requires JOIN support')
def test_bug_17944_unknown_password_algorithm(self):
user = User.objects.get(username='unknown_password')
form = UserChangeForm(instance=user)
Expand Down
5 changes: 4 additions & 1 deletion django/contrib/auth/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from django.test.utils import override_settings
from django.contrib.auth.models import (Group, User,
SiteProfileNotAvailable, UserManager)

from django.db import router, connections
from django.utils import unittest

class ProfileTestCase(TestCase):
fixtures = ['authtestdata.json']
Expand Down Expand Up @@ -59,6 +60,7 @@ def test_group_natural_key(self):
class LoadDataWithoutNaturalKeysTestCase(TestCase):
fixtures = ['regular.json']

@unittest.skipIf(not connections[router.db_for_read(User)].features.supports_joins, 'Requires JOIN support')
def test_user_is_created_and_added_to_group(self):
user = User.objects.get(username='my_username')
group = Group.objects.get(name='my_group')
Expand All @@ -70,6 +72,7 @@ def test_user_is_created_and_added_to_group(self):
class LoadDataWithNaturalKeysTestCase(TestCase):
fixtures = ['natural.json']

@unittest.skipIf(not connections[router.db_for_read(User)].features.supports_joins, 'Requires JOIN support')
def test_user_is_created_and_added_to_group(self):
user = User.objects.get(username='my_username')
group = Group.objects.get(name='my_group')
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{ protocol }}://{{ domain }}/reset/{{ uid }}-{{ token }}/
{{ protocol }}://{{ domain }}/reset/{{ uid }}/{{ token }}/
6 changes: 3 additions & 3 deletions django/contrib/auth/tests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def test_named_urls(self):
('password_reset', [], {}),
('password_reset_done', [], {}),
('password_reset_confirm', [], {
'uidb36': 'aaaaaaa',
'uidb64': 'aaaaaaa',
'token': '1111-aaaaa',
}),
('password_reset_complete', [], {}),
Expand Down Expand Up @@ -178,13 +178,13 @@ def test_confirm_invalid(self):

def test_confirm_invalid_user(self):
# Ensure that we get a 200 response for a non-existant user, not a 404
response = self.client.get('/reset/123456-1-1/')
response = self.client.get('/reset/123456/1-1/')
self.assertEqual(response.status_code, 200)
self.assertTrue("The password reset link was invalid" in response.content)

def test_confirm_overflow_user(self):
# Ensure that we get a 200 response for a base36 user id that overflows int
response = self.client.get('/reset/zzzzzzzzzzzzz-1-1/')
response = self.client.get('/reset/zzzzzzzzzzzzz/1-1/')
self.assertEqual(response.status_code, 200)
self.assertTrue("The password reset link was invalid" in response.content)

Expand Down
2 changes: 1 addition & 1 deletion django/contrib/auth/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
url(r'^password_change/done/$', 'django.contrib.auth.views.password_change_done', name='password_change_done'),
url(r'^password_reset/$', 'django.contrib.auth.views.password_reset', name='password_reset'),
url(r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done', name='password_reset_done'),
url(r'^reset/(?P<uidb36>[0-9A-Za-z]{1,13})-(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),
url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete'),
Expand Down
12 changes: 6 additions & 6 deletions django/contrib/auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, QueryDict
from django.template.response import TemplateResponse
from django.utils.http import base36_to_int, is_safe_url
from django.utils.http import is_safe_url, urlsafe_base64_decode
from django.utils.translation import ugettext as _
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.cache import never_cache
Expand Down Expand Up @@ -174,7 +174,7 @@ def password_reset_done(request,
# Doesn't need csrf_protect since no-one can guess the URL
@sensitive_post_parameters()
@never_cache
def password_reset_confirm(request, uidb36=None, token=None,
def password_reset_confirm(request, uidb64=None, token=None,
template_name='registration/password_reset_confirm.html',
token_generator=default_token_generator,
set_password_form=SetPasswordForm,
Expand All @@ -184,13 +184,13 @@ def password_reset_confirm(request, uidb36=None, token=None,
View that checks the hash in a password reset link and presents a
form for entering a new password.
"""
assert uidb36 is not None and token is not None # checked by URLconf
assert uidb64 is not None and token is not None # checked by URLconf
if post_reset_redirect is None:
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_complete')
try:
uid_int = base36_to_int(uidb36)
user = User.objects.get(id=uid_int)
except (ValueError, User.DoesNotExist):
uid = urlsafe_base64_decode(str(uidb64))
user = User.objects.get(id=uid)
except (TypeError, ValueError, User.DoesNotExist):
user = None

if user is not None and token_generator.check_token(user, token):
Expand Down
6 changes: 4 additions & 2 deletions django/contrib/contenttypes/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import urllib

from django.db import models
from django.db import models, router, connections
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.views import shortcut
from django.contrib.sites.models import Site
from django.http import HttpRequest, Http404
from django.test import TestCase
from django.utils.encoding import smart_str

from django.utils import unittest

class FooWithoutUrl(models.Model):
"""
Expand Down Expand Up @@ -114,6 +114,7 @@ def test_get_for_models_full_cache(self):
FooWithUrl: ContentType.objects.get_for_model(FooWithUrl),
})

@unittest.skipIf(not connections[router.db_for_read(FooWithUrl)].features.supports_joins, 'Requires JOIN support')
def test_shortcut_view(self):
"""
Check that the shortcut view (used for the admin "view on site"
Expand Down Expand Up @@ -156,6 +157,7 @@ def test_shortcut_view_without_get_absolute_url(self):

self.assertRaises(Http404, shortcut, request, user_ct.id, obj.id)

@unittest.skipIf(not connections[router.db_for_read(FooWithBrokenAbsoluteUrl)].features.supports_joins, 'Requires JOIN support')
def test_shortcut_view_with_broken_get_absolute_url(self):
"""
Check that the shortcut view does not catch an AttributeError raised
Expand Down
6 changes: 5 additions & 1 deletion django/core/files/uploadhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def handle_raw_input(self, input_data, META, content_length, boundary, encoding=
"""
pass

def new_file(self, field_name, file_name, content_type, content_length, charset=None):
def new_file(self, field_name, file_name, content_type, content_length,
charset=None, content_type_extra=None):
"""
Signal that a new file has been started.

Expand All @@ -96,6 +97,9 @@ def new_file(self, field_name, file_name, content_type, content_length, charset=
self.content_type = content_type
self.content_length = content_length
self.charset = charset
if content_type_extra is None:
content_type_extra = {}
self.content_type_extra = content_type_extra

def receive_data_chunk(self, raw_data, start):
"""
Expand Down
14 changes: 13 additions & 1 deletion django/core/serializers/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,21 @@ def handle_m2m_field(self, obj, field):
if field.rel.through._meta.auto_created:
if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'):
m2m_value = lambda value: value.natural_key()
self._current[field.name] = [m2m_value(related)
for related in getattr(obj, field.name).iterator()]
elif field.rel.get_related_field().primary_key:
m2m_value = lambda value: smart_unicode(
getattr(value, related_query.target_field_name + '_id'),
strings_only=True)
related_query = getattr(obj, field.name)
filters = {related_query.source_field_name: obj._get_pk_val()}
query = field.rel.through.objects.filter(**filters)
self._current[field.name] = sorted((m2m_value(m2m_entity)
for m2m_entity in query),
reverse=True)
else:
m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True)
self._current[field.name] = [m2m_value(related)
self._current[field.name] = [m2m_value(related)
for related in getattr(obj, field.name).iterator()]

def getvalue(self):
Expand Down
11 changes: 11 additions & 0 deletions django/db/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ class BaseDatabaseFeatures(object):
has_select_for_update = False
has_select_for_update_nowait = False

distinguishes_insert_from_update = True
supports_joins = True
supports_select_related = True

# Does the default test database allow multiple connections?
Expand Down Expand Up @@ -778,6 +780,15 @@ def prep_for_like_query(self, x):
# need not necessarily be implemented using "LIKE" in the backend.
prep_for_iexact_query = prep_for_like_query

def value_to_db_auto(self, value):
"""
Transform an AutoField value to an object compatible with what is expected
by the backend driver for automatic keys.
"""
if value is None:
return None
return int(value)

def value_to_db_date(self, value):
"""
Transform a date value to an object compatible with what is expected
Expand Down
Loading