Port new code to Python 3 as well, fix six.with_metaclass() issues

Many thanks to @atheiste for the big porting steps!
fix_request_path_info
Diederik van der Boor 2013-04-08 01:04:00 +02:00
parent cbf52a61af
commit 4d7d33ed0d
6 changed files with 40 additions and 20 deletions

View File

@ -2,6 +2,7 @@ language: python
python: python:
- "2.6" - "2.6"
- "2.7" - "2.7"
- "3.3"
env: env:
- DJANGO=django==1.4.5 - DJANGO=django==1.4.5
- DJANGO=django==1.5 - DJANGO=django==1.5

View File

@ -54,6 +54,13 @@ class PolymorphicModelBase(ModelBase):
def __new__(self, model_name, bases, attrs): def __new__(self, model_name, bases, attrs):
#print; print '###', model_name, '- bases:', bases #print; print '###', model_name, '- bases:', bases
# Workaround compatibility issue with six.with_metaclass() and custom Django model metaclasses:
# Let Django fully ignore the class which is inserted in between.
if not attrs and model_name == 'NewBase':
attrs['__module__'] = 'django.utils.six'
attrs['Meta'] = type('Meta', (), {'abstract': True})
return super(PolymorphicModelBase, self).__new__(self, model_name, bases, attrs)
# create new model # create new model
new_class = self.call_superclass_new_method(model_name, bases, attrs) new_class = self.call_superclass_new_method(model_name, bases, attrs)
@ -145,7 +152,7 @@ class PolymorphicModelBase(ModelBase):
# The ordering in the base.__dict__ may randomly change depending on which method is added. # The ordering in the base.__dict__ may randomly change depending on which method is added.
# Make sure base_objects is on top, and 'objects' and '_default_manager' follow afterwards. # Make sure base_objects is on top, and 'objects' and '_default_manager' follow afterwards.
# This makes sure that the _base_manager is also assigned properly. # This makes sure that the _base_manager is also assigned properly.
add_managers = sorted(add_managers, key=lambda item: item[2].creation_counter, reverse=True) add_managers = sorted(add_managers, key=lambda item: (item[1].startswith('_'), item[1]))
return add_managers return add_managers
@classmethod @classmethod
@ -178,9 +185,8 @@ class PolymorphicModelBase(ModelBase):
# which is directly in the python path. To work around this we temporarily set # which is directly in the python path. To work around this we temporarily set
# app_label here for PolymorphicModel. # app_label here for PolymorphicModel.
meta = attrs.get('Meta', None) meta = attrs.get('Meta', None)
model_module_name = attrs['__module__']
do_app_label_workaround = (meta do_app_label_workaround = (meta
and model_module_name == 'polymorphic' and attrs['__module__'] == 'polymorphic'
and model_name == 'PolymorphicModel' and model_name == 'PolymorphicModel'
and getattr(meta, 'app_label', None) is None) and getattr(meta, 'app_label', None) is None)

View File

@ -34,7 +34,7 @@ def translate_polymorphic_filter_definitions_in_kwargs(queryset_model, kwargs):
Returns: a list of non-keyword-arguments (Q objects) to be added to the filter() query. Returns: a list of non-keyword-arguments (Q objects) to be added to the filter() query.
""" """
additional_args = [] additional_args = []
for field_path, val in kwargs.items(): for field_path, val in kwargs.copy().items(): # Python 3 needs copy
new_expr = _translate_polymorphic_filter_definition(queryset_model, field_path, val) new_expr = _translate_polymorphic_filter_definition(queryset_model, field_path, val)

View File

@ -2,6 +2,7 @@
""" Test Cases """ Test Cases
Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/ Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/
""" """
from __future__ import print_function
import uuid import uuid
import re import re
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
@ -10,6 +11,7 @@ from django.test import TestCase
from django.db.models import Q,Count from django.db.models import Q,Count
from django.db import models from django.db import models
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils import six
from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet
from polymorphic import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent from polymorphic import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
@ -253,10 +255,10 @@ class PolymorphicTests(TestCase):
o2 = DiamondXY.objects.get() o2 = DiamondXY.objects.get()
if o2.field_b != 'b': if o2.field_b != 'b':
print print('')
print '# known django model inheritance diamond problem detected' print('# known django model inheritance diamond problem detected')
print 'DiamondXY fields 1: field_b "{0}", field_x "{1}", field_y "{2}"'.format(o1.field_b, o1.field_x, o1.field_y) print('DiamondXY fields 1: field_b "{0}", field_x "{1}", field_y "{2}"'.format(o1.field_b, o1.field_x, o1.field_y))
print 'DiamondXY fields 2: field_b "{0}", field_x "{1}", field_y "{2}"'.format(o2.field_b, o2.field_x, o2.field_y) print('DiamondXY fields 2: field_b "{0}", field_x "{1}", field_y "{2}"'.format(o2.field_b, o2.field_x, o2.field_y))
def test_annotate_aggregate_order(self): def test_annotate_aggregate_order(self):
@ -363,16 +365,16 @@ class PolymorphicTests(TestCase):
<UUIDResearchProject: uuid_primary_key (UUIDField/pk), topic (CharField) "Swallow Aerodynamics", supervisor (CharField) "Dr. Winter"> ]""" <UUIDResearchProject: uuid_primary_key (UUIDField/pk), topic (CharField) "Swallow Aerodynamics", supervisor (CharField) "Dr. Winter"> ]"""
self.assertEqual(res, res_exp) self.assertEqual(res, res_exp)
#if (a.pk!= uuid.UUID or c.pk!= uuid.UUID): #if (a.pk!= uuid.UUID or c.pk!= uuid.UUID):
# print # print()
# print '# known inconstency with custom primary key field detected (django problem?)' # print('# known inconstency with custom primary key field detected (django problem?)')
a = UUIDPlainA.objects.create(field1='A1') a = UUIDPlainA.objects.create(field1='A1')
b = UUIDPlainB.objects.create(field1='B1', field2='B2') b = UUIDPlainB.objects.create(field1='B1', field2='B2')
c = UUIDPlainC.objects.create(field1='C1', field2='C2', field3='C3') c = UUIDPlainC.objects.create(field1='C1', field2='C2', field3='C3')
qs = UUIDPlainA.objects.all() qs = UUIDPlainA.objects.all()
if a.pk!= uuid.UUID or c.pk!= uuid.UUID: if a.pk!= uuid.UUID or c.pk!= uuid.UUID:
print print('')
print '# known type inconstency with custom primary key field detected (django problem?)' print('# known type inconstency with custom primary key field detected (django problem?)')
def create_model2abcd(self): def create_model2abcd(self):
@ -531,9 +533,14 @@ class PolymorphicTests(TestCase):
ModelExtraExternal.objects.create(topic='extra2') ModelExtraExternal.objects.create(topic='extra2')
ModelExtraExternal.objects.create(topic='extra3') ModelExtraExternal.objects.create(topic='extra3')
objects = ModelExtraA.objects.extra(tables=["polymorphic_modelextraexternal"], select={"topic":"polymorphic_modelextraexternal.topic"}, where=["polymorphic_modelextraa.id = polymorphic_modelextraexternal.id"]) objects = ModelExtraA.objects.extra(tables=["polymorphic_modelextraexternal"], select={"topic":"polymorphic_modelextraexternal.topic"}, where=["polymorphic_modelextraa.id = polymorphic_modelextraexternal.id"])
self.assertEqual(repr(objects[0]), '<ModelExtraA: id 1, field1 (CharField) "A1" - Extra: topic (unicode) "extra1">') if six.PY3:
self.assertEqual(repr(objects[1]), '<ModelExtraB: id 2, field1 (CharField) "B1", field2 (CharField) "B2" - Extra: topic (unicode) "extra2">') self.assertEqual(repr(objects[0]), '<ModelExtraA: id 1, field1 (CharField) "A1" - Extra: topic (str) "extra1">')
self.assertEqual(repr(objects[2]), '<ModelExtraC: id 3, field1 (CharField) "C1", field2 (CharField) "C2", field3 (CharField) "C3" - Extra: topic (unicode) "extra3">') self.assertEqual(repr(objects[1]), '<ModelExtraB: id 2, field1 (CharField) "B1", field2 (CharField) "B2" - Extra: topic (str) "extra2">')
self.assertEqual(repr(objects[2]), '<ModelExtraC: id 3, field1 (CharField) "C1", field2 (CharField) "C2", field3 (CharField) "C3" - Extra: topic (str) "extra3">')
else:
self.assertEqual(repr(objects[0]), '<ModelExtraA: id 1, field1 (CharField) "A1" - Extra: topic (unicode) "extra1">')
self.assertEqual(repr(objects[1]), '<ModelExtraB: id 2, field1 (CharField) "B1", field2 (CharField) "B2" - Extra: topic (unicode) "extra2">')
self.assertEqual(repr(objects[2]), '<ModelExtraC: id 3, field1 (CharField) "C1", field2 (CharField) "C2", field3 (CharField) "C3" - Extra: topic (unicode) "extra3">')
self.assertEqual(len(objects), 3) self.assertEqual(len(objects), 3)

View File

@ -6,7 +6,7 @@ import uuid
from django import forms from django import forms
from django.db import models from django.db import models
from django.utils.encoding import smart_unicode from django.utils.encoding import smart_text
from django.utils import six from django.utils import six
class UUIDVersionError(Exception): class UUIDVersionError(Exception):
@ -98,7 +98,7 @@ class UUIDField(six.with_metaclass(models.SubfieldBase, models.CharField)):
if isinstance(value, uuid.UUID): if isinstance(value, uuid.UUID):
return value return value
# attempt to parse a UUID # attempt to parse a UUID
return uuid.UUID(smart_unicode(value)) return uuid.UUID(smart_text(value))
# #
# If I do the following (returning a String instead of a UUID # If I do the following (returning a String instead of a UUID
@ -108,7 +108,7 @@ class UUIDField(six.with_metaclass(models.SubfieldBase, models.CharField)):
#if not value: #if not value:
# return None # return None
#if isinstance(value, uuid.UUID): #if isinstance(value, uuid.UUID):
# return smart_unicode(value) # return smart_text(value)
#else: #else:
# return value # return value
@ -126,7 +126,7 @@ class UUIDField(six.with_metaclass(models.SubfieldBase, models.CharField)):
def get_db_prep_value(self, value, connection, prepared): def get_db_prep_value(self, value, connection, prepared):
"""Casts uuid.UUID values into the format expected by the back end for use in queries""" """Casts uuid.UUID values into the format expected by the back end for use in queries"""
if isinstance(value, uuid.UUID): if isinstance(value, uuid.UUID):
return smart_unicode(value) return smart_text(value)
return value return value
def value_to_string(self, obj): def value_to_string(self, obj):
@ -134,7 +134,7 @@ class UUIDField(six.with_metaclass(models.SubfieldBase, models.CharField)):
if val is None: if val is None:
data = '' data = ''
else: else:
data = smart_unicode(val) data = smart_text(val)
return data return data
def formfield(self, **kwargs): def formfield(self, **kwargs):

View File

@ -1,5 +1,6 @@
[tox] [tox]
envlist= envlist=
py33-django15,
py26-django15, py26-django15,
py27-django15, py27-django15,
py26-django14, py26-django14,
@ -31,3 +32,8 @@ basepython=python2.7
deps= deps=
django==1.4.5 django==1.4.5
[testenv:py33-django15]
basepython=python3.3
deps=
django==1.5