Fixed #6052 -- Worked around a bug in MySQLdb with regards to handling

SafeUnicode (handle SafeString similarly, just to be safe). Based on a patch
from sfllaw.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@9467 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-11-16 08:50:06 +00:00
parent 9d0bacebd2
commit 1418da7ee4
2 changed files with 15 additions and 12 deletions

View File

@ -29,6 +29,7 @@ from django.db.backends.mysql.client import DatabaseClient
from django.db.backends.mysql.creation import DatabaseCreation from django.db.backends.mysql.creation import DatabaseCreation
from django.db.backends.mysql.introspection import DatabaseIntrospection from django.db.backends.mysql.introspection import DatabaseIntrospection
from django.db.backends.mysql.validation import DatabaseValidation from django.db.backends.mysql.validation import DatabaseValidation
from django.utils.safestring import SafeString, SafeUnicode
# Raise exceptions for database warnings if DEBUG is on # Raise exceptions for database warnings if DEBUG is on
from django.conf import settings from django.conf import settings
@ -39,12 +40,11 @@ if settings.DEBUG:
DatabaseError = Database.DatabaseError DatabaseError = Database.DatabaseError
IntegrityError = Database.IntegrityError IntegrityError = Database.IntegrityError
# MySQLdb-1.2.1 supports the Python boolean type, and only uses datetime # MySQLdb-1.2.1 returns TIME columns as timedelta -- they are more like
# module for time-related columns; older versions could have used mx.DateTime # timedelta in terms of actual behavior as they are signed and include days --
# or strings if there were no datetime module. However, MySQLdb still returns # and Django expects time, so we still need to override that. We also need to
# TIME columns as timedelta -- they are more like timedelta in terms of actual # add special handling for SafeUnicode and SafeString as MySQLdb's type
# behavior as they are signed and include days -- and Django expects time, so # checking is too tight to catch those (see Django ticket #6052).
# we still need to override that.
django_conversions = conversions.copy() django_conversions = conversions.copy()
django_conversions.update({ django_conversions.update({
FIELD_TYPE.TIME: util.typecast_time, FIELD_TYPE.TIME: util.typecast_time,
@ -174,7 +174,7 @@ class DatabaseOperations(BaseDatabaseOperations):
def value_to_db_datetime(self, value): def value_to_db_datetime(self, value):
if value is None: if value is None:
return None return None
# MySQL doesn't support tz-aware datetimes # MySQL doesn't support tz-aware datetimes
if value.tzinfo is not None: if value.tzinfo is not None:
raise ValueError("MySQL backend does not support timezone-aware datetimes.") raise ValueError("MySQL backend does not support timezone-aware datetimes.")
@ -185,11 +185,11 @@ class DatabaseOperations(BaseDatabaseOperations):
def value_to_db_time(self, value): def value_to_db_time(self, value):
if value is None: if value is None:
return None return None
# MySQL doesn't support tz-aware datetimes # MySQL doesn't support tz-aware datetimes
if value.tzinfo is not None: if value.tzinfo is not None:
raise ValueError("MySQL backend does not support timezone-aware datetimes.") raise ValueError("MySQL backend does not support timezone-aware datetimes.")
# MySQL doesn't support microseconds # MySQL doesn't support microseconds
return unicode(value.replace(microsecond=0)) return unicode(value.replace(microsecond=0))
@ -260,6 +260,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
kwargs['port'] = int(settings.DATABASE_PORT) kwargs['port'] = int(settings.DATABASE_PORT)
kwargs.update(self.options) kwargs.update(self.options)
self.connection = Database.connect(**kwargs) self.connection = Database.connect(**kwargs)
self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
self.connection.encoders[SafeString] = self.connection.encoders[str]
cursor = CursorWrapper(self.connection.cursor()) cursor = CursorWrapper(self.connection.cursor())
return cursor return cursor

View File

@ -1,3 +1,4 @@
# coding: utf-8
""" """
32. Callable defaults 32. Callable defaults
@ -19,7 +20,7 @@ class Article(models.Model):
def __unicode__(self): def __unicode__(self):
return self.headline return self.headline
__test__ = {'API_TESTS':""" __test__ = {'API_TESTS': u"""
>>> from datetime import datetime >>> from datetime import datetime
# No articles are in the system yet. # No articles are in the system yet.
@ -51,8 +52,8 @@ True
# make sure that SafeString/SafeUnicode fields work # make sure that SafeString/SafeUnicode fields work
>>> from django.utils.safestring import SafeUnicode, SafeString >>> from django.utils.safestring import SafeUnicode, SafeString
>>> a.headline = SafeUnicode(u'SafeUnicode Headline') >>> a.headline = SafeUnicode(u'Iñtërnâtiônàlizætiøn1')
>>> a.save() >>> a.save()
>>> a.headline = SafeString(u'SafeString Headline') >>> a.headline = SafeString(u'Iñtërnâtiônàlizætiøn1'.encode('utf-8'))
>>> a.save() >>> a.save()
"""} """}