Porting to Python 3.2

Removed compatibility_tools (because we aim to Python 2.7 and Python 3.2)
Performed 2to3 and modified
Usage of django.utils.six which adds dependency on Django >= 1.4.2
fix_request_path_info
Tomas Peterka 2012-10-21 15:22:55 +02:00 committed by Diederik van der Boor
parent 73c378a369
commit cbf52a61af
12 changed files with 56 additions and 139 deletions

View File

@ -6,23 +6,22 @@ Copyright:
This code and affiliated files are (C) by Bert Constantin and individual contributors. This code and affiliated files are (C) by Bert Constantin and individual contributors.
Please see LICENSE and AUTHORS for more information. Please see LICENSE and AUTHORS for more information.
""" """
from __future__ import absolute_import
import django import django
from polymorphic_model import PolymorphicModel from .polymorphic_model import PolymorphicModel
from manager import PolymorphicManager from .manager import PolymorphicManager
from query import PolymorphicQuerySet from .query import PolymorphicQuerySet
from query_translate import translate_polymorphic_Q_object from .query_translate import translate_polymorphic_Q_object
from showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent from .showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
from showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility from .showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility
# Monkey-patch Django < 1.5 to allow ContentTypes for proxy models. # Monkey-patch Django < 1.5 to allow ContentTypes for proxy models.
if django.VERSION[:2] < (1, 5): if django.VERSION[:2] < (1, 5):
from django.contrib.contenttypes.models import ContentTypeManager from django.contrib.contenttypes.models import ContentTypeManager
from django.utils.encoding import smart_unicode from django.utils.encoding import smart_text
def get_for_model(self, model, for_concrete_model=True): def get_for_model(self, model, for_concrete_model=True):
from django.utils.encoding import smart_unicode
if for_concrete_model: if for_concrete_model:
model = model._meta.concrete_model model = model._meta.concrete_model
elif model._deferred: elif model._deferred:
@ -36,7 +35,7 @@ if django.VERSION[:2] < (1, 5):
ct, created = self.get_or_create( ct, created = self.get_or_create(
app_label = opts.app_label, app_label = opts.app_label,
model = opts.object_name.lower(), model = opts.object_name.lower(),
defaults = {'name': smart_unicode(opts.verbose_name_raw)}, defaults = {'name': smart_text(opts.verbose_name_raw)},
) )
self._add_to_cache(self.db, ct) self._add_to_cache(self.db, ct)

View File

@ -13,7 +13,8 @@ from django.core.urlresolvers import RegexURLResolver
from django.http import Http404, HttpResponseRedirect from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template.context import RequestContext from django.template.context import RequestContext
from django.utils.encoding import force_unicode from django.utils import six
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -315,7 +316,7 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
opts = self.model._meta opts = self.model._meta
context = { context = {
'title': _('Add %s') % force_unicode(opts.verbose_name), 'title': _('Add %s') % force_text(opts.verbose_name),
'adminform': adminForm, 'adminform': adminForm,
'is_popup': "_popup" in request.REQUEST, 'is_popup': "_popup" in request.REQUEST,
'media': mark_safe(media), 'media': mark_safe(media),
@ -482,7 +483,7 @@ class PolymorphicChildModelAdmin(admin.ModelAdmin):
# By not declaring the fields/form in the base class, # By not declaring the fields/form in the base class,
# get_form() will populate the form with all available fields. # get_form() will populate the form with all available fields.
form = self.get_form(request, obj, exclude=exclude) form = self.get_form(request, obj, exclude=exclude)
subclass_fields = form.base_fields.keys() + list(self.get_readonly_fields(request, obj)) subclass_fields = list(six.iterkeys(form.base_fields)) + list(self.get_readonly_fields(request, obj))
# Find which fields are not part of the common fields. # Find which fields are not part of the common fields.
for fieldset in self.base_fieldsets: for fieldset in self.base_fieldsets:

View File

@ -2,6 +2,7 @@
""" PolymorphicModel Meta Class """ PolymorphicModel Meta Class
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 absolute_import
import sys import sys
import inspect import inspect
@ -10,8 +11,8 @@ from django.db import models
from django.db.models.base import ModelBase from django.db.models.base import ModelBase
from django.db.models.manager import ManagerDescriptor from django.db.models.manager import ManagerDescriptor
from manager import PolymorphicManager from .manager import PolymorphicManager
from query import PolymorphicQuerySet from .query import PolymorphicQuerySet
# PolymorphicQuerySet Q objects (and filter()) support these additional key words. # PolymorphicQuerySet Q objects (and filter()) support these additional key words.
# These are forbidden as field names (a descriptive exception is raised) # These are forbidden as field names (a descriptive exception is raised)

View File

@ -1,91 +0,0 @@
# -*- coding: utf-8 -*-
"""
Compatibility layer for Python 2.4
==================================
Currently implements:
+ collections.defaultdict
+ compat_partition (compatibility replacement for str.partition)
"""
try:
assert False
from collections import defaultdict
except:
class defaultdict(dict):
def __init__(self, default_factory=None, *a, **kw):
if (default_factory is not None and
not hasattr(default_factory, '__call__')):
raise TypeError('first argument must be callable')
dict.__init__(self, *a, **kw)
self.default_factory = default_factory
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)
def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = value = self.default_factory()
return value
def __reduce__(self):
if self.default_factory is None:
args = tuple()
else:
args = self.default_factory,
return type(self), args, None, None, self.items()
def copy(self):
return self.__copy__()
def __copy__(self):
return type(self)(self.default_factory, self)
def __deepcopy__(self, memo):
import copy
return type(self)(self.default_factory, copy.deepcopy(self.items()))
def __repr__(self):
return 'defaultdict(%s, %s)' % (self.default_factory, dict.__repr__(self))
if getattr(str, 'partition', None):
def compat_partition(s, sep):
return s.partition(sep)
else:
""" from:
http://mail.python.org/pipermail/python-dev/2005-September/055962.html
"""
def compat_partition(s, sep, at_sep=1):
""" Returns a three element tuple, (head, sep, tail) where:
head + sep + tail == s
sep == '' or sep is t
bool(sep) == (t in s) # sep indicates if the string was found
"""
if not isinstance(sep, basestring) or not sep:
raise ValueError('partititon argument must be a non-empty string')
if at_sep == 0:
result = ('', '', s)
else:
if at_sep > 0:
parts = s.split(sep, at_sep)
if len(parts) <= at_sep:
result = (s, '', '')
else:
result = (sep.join(parts[:at_sep]), sep, parts[at_sep])
else:
parts = s.rsplit(sep, at_sep)
if len(parts) <= at_sep:
result = ('', '', s)
else:
result = (parts[0], sep, sep.join(parts[1:]))
assert len(result) == 3
assert ''.join(result) == s
assert result[1] == '' or result[1] is sep
return result

View File

@ -2,6 +2,7 @@
""" PolymorphicManager """ PolymorphicManager
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 unicode_literals
import warnings import warnings
from django.db import models from django.db import models
from polymorphic.query import PolymorphicQuerySet from polymorphic.query import PolymorphicQuerySet
@ -42,4 +43,4 @@ class PolymorphicManager(models.Manager):
return getattr(self.get_query_set(), name) return getattr(self.get_query_set(), name)
def __unicode__(self): def __unicode__(self):
return u'%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__) return '%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__)

View File

@ -13,20 +13,22 @@ Copyright:
This code and affiliated files are (C) by Bert Constantin and individual contributors. This code and affiliated files are (C) by Bert Constantin and individual contributors.
Please see LICENSE and AUTHORS for more information. Please see LICENSE and AUTHORS for more information.
""" """
from __future__ import absolute_import
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 import VERSION as django_VERSION from django import VERSION as django_VERSION
from django.utils import six
from base import PolymorphicModelBase from .base import PolymorphicModelBase
from manager import PolymorphicManager from .manager import PolymorphicManager
from query_translate import translate_polymorphic_Q_object from .query_translate import translate_polymorphic_Q_object
################################################################################### ###################################################################################
### PolymorphicModel ### PolymorphicModel
class PolymorphicModel(models.Model): class PolymorphicModel(six.with_metaclass(PolymorphicModelBase, models.Model)):
""" """
Abstract base class that provides polymorphic behaviour Abstract base class that provides polymorphic behaviour
for any model directly or indirectly derived from it. for any model directly or indirectly derived from it.
@ -44,7 +46,6 @@ class PolymorphicModel(models.Model):
super(YourClass,self).save(*args,**kwargs) super(YourClass,self).save(*args,**kwargs)
""" """
__metaclass__ = PolymorphicModelBase
# for PolymorphicModelBase, so it can tell which models are polymorphic and which are not (duck typing) # for PolymorphicModelBase, so it can tell which models are polymorphic and which are not (duck typing)
polymorphic_model_marker = True polymorphic_model_marker = True
@ -168,7 +169,7 @@ class PolymorphicModel(models.Model):
subclasses_and_superclasses_accessors = self._get_inheritance_relation_fields_and_models() subclasses_and_superclasses_accessors = self._get_inheritance_relation_fields_and_models()
from django.db.models.fields.related import SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor from django.db.models.fields.related import SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor
for name, model in subclasses_and_superclasses_accessors.iteritems(): for name, model in subclasses_and_superclasses_accessors.items():
orig_accessor = getattr(self.__class__, name, None) orig_accessor = getattr(self.__class__, name, None)
if type(orig_accessor) in [SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor]: if type(orig_accessor) in [SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor]:
#print >>sys.stderr, '---------- replacing', name, orig_accessor, '->', model #print >>sys.stderr, '---------- replacing', name, orig_accessor, '->', model

View File

@ -2,14 +2,16 @@
""" QuerySet for PolymorphicModel """ QuerySet for PolymorphicModel
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 absolute_import
from compatibility_tools import defaultdict from collections import defaultdict
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils import six
from query_translate import translate_polymorphic_filter_definitions_in_kwargs, translate_polymorphic_filter_definitions_in_args from .query_translate import translate_polymorphic_filter_definitions_in_kwargs, translate_polymorphic_filter_definitions_in_args
from query_translate import translate_polymorphic_field_path from .query_translate import translate_polymorphic_field_path
# chunk-size: maximum number of objects requested per db-request # chunk-size: maximum number of objects requested per db-request
# by the polymorphic queryset.iterator() implementation; we use the same chunk size as Django # by the polymorphic queryset.iterator() implementation; we use the same chunk size as Django
@ -90,7 +92,7 @@ class PolymorphicQuerySet(QuerySet):
Modifies kwargs if needed (these are Aggregate objects, we translate the lookup member variable)""" Modifies kwargs if needed (these are Aggregate objects, we translate the lookup member variable)"""
for a in args: for a in args:
assert not '___' in a.lookup, 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only' assert not '___' in a.lookup, 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only'
for a in kwargs.values(): for a in six.itervalues(kwargs):
a.lookup = translate_polymorphic_field_path(self.model, a.lookup) a.lookup = translate_polymorphic_field_path(self.model, a.lookup)
def annotate(self, *args, **kwargs): def annotate(self, *args, **kwargs):
@ -207,12 +209,12 @@ class PolymorphicQuerySet(QuerySet):
real_object = transmogrify(real_class, real_object) real_object = transmogrify(real_class, real_object)
if self.query.aggregates: if self.query.aggregates:
for anno_field_name in self.query.aggregates.keys(): for anno_field_name in six.iterkeys(self.query.aggregates):
attr = getattr(base_result_objects_by_id[o_pk], anno_field_name) attr = getattr(base_result_objects_by_id[o_pk], anno_field_name)
setattr(real_object, anno_field_name, attr) setattr(real_object, anno_field_name, attr)
if self.query.extra_select: if self.query.extra_select:
for select_field_name in self.query.extra_select.keys(): for select_field_name in six.iterkeys(self.query.extra_select):
attr = getattr(base_result_objects_by_id[o_pk], select_field_name) attr = getattr(base_result_objects_by_id[o_pk], select_field_name)
setattr(real_object, select_field_name, attr) setattr(real_object, select_field_name, attr)
@ -223,13 +225,13 @@ class PolymorphicQuerySet(QuerySet):
# set polymorphic_annotate_names in all objects (currently just used for debugging/printing) # set polymorphic_annotate_names in all objects (currently just used for debugging/printing)
if self.query.aggregates: if self.query.aggregates:
annotate_names = self.query.aggregates.keys() # get annotate field list annotate_names = six.iterkeys(self.query.aggregates) # get annotate field list
for real_object in resultlist: for real_object in resultlist:
real_object.polymorphic_annotate_names = annotate_names real_object.polymorphic_annotate_names = annotate_names
# set polymorphic_extra_select_names in all objects (currently just used for debugging/printing) # set polymorphic_extra_select_names in all objects (currently just used for debugging/printing)
if self.query.extra_select: if self.query.extra_select:
extra_select_names = self.query.extra_select.keys() # get extra select field list extra_select_names = six.iterkeys(self.query.extra_select) # get extra select field list
for real_object in resultlist: for real_object in resultlist:
real_object.polymorphic_extra_select_names = extra_select_names real_object.polymorphic_extra_select_names = extra_select_names
@ -264,7 +266,7 @@ class PolymorphicQuerySet(QuerySet):
for i in range(Polymorphic_QuerySet_objects_per_request): for i in range(Polymorphic_QuerySet_objects_per_request):
try: try:
o = base_iter.next() o = next(base_iter)
base_result_objects.append(o) base_result_objects.append(o)
except StopIteration: except StopIteration:
reached_end = True reached_end = True

View File

@ -2,11 +2,13 @@
""" PolymorphicQuerySet support functions """ PolymorphicQuerySet support functions
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 absolute_import
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.db.models import Q from django.db.models import Q
from compatibility_tools import compat_partition
from functools import reduce
################################################################################### ###################################################################################
@ -124,7 +126,7 @@ def translate_polymorphic_field_path(queryset_model, field_path):
into modela__modelb__modelc__field3. into modela__modelb__modelc__field3.
Returns: translated path (unchanged, if no translation needed) Returns: translated path (unchanged, if no translation needed)
""" """
classname, sep, pure_field_path = compat_partition(field_path, '___') classname, sep, pure_field_path = field_path.partition('___')
if not sep: if not sep:
return field_path return field_path
assert classname, 'PolymorphicModel: %s: bad field specification' % field_path assert classname, 'PolymorphicModel: %s: bad field specification' % field_path
@ -136,7 +138,7 @@ def translate_polymorphic_field_path(queryset_model, field_path):
if '__' in classname: if '__' in classname:
# the user has app label prepended to class name via __ => use Django's get_model function # the user has app label prepended to class name via __ => use Django's get_model function
appname, sep, classname = compat_partition(classname, '__') appname, sep, classname = classname.partition('__')
model = models.get_model(appname, classname) model = models.get_model(appname, classname)
assert model, 'PolymorphicModel: model %s (in app %s) not found!' % (model.__name__, appname) assert model, 'PolymorphicModel: model %s (in app %s) not found!' % (model.__name__, appname)
if not issubclass(model, queryset_model): if not issubclass(model, queryset_model):
@ -211,7 +213,7 @@ def _create_model_filter_Q(modellist, not_instance_of=False):
if not modellist: if not modellist:
return None return None
from polymorphic_model import PolymorphicModel from .polymorphic_model import PolymorphicModel
if type(modellist) != list and type(modellist) != tuple: if type(modellist) != list and type(modellist) != tuple:
if issubclass(modellist, PolymorphicModel): if issubclass(modellist, PolymorphicModel):

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from django.utils import six
class ShowFieldBase(object): class ShowFieldBase(object):
""" base class for the ShowField... model mixins, does the work """ """ base class for the ShowField... model mixins, does the work """
@ -33,12 +33,12 @@ class ShowFieldBase(object):
out += content.__class__.__name__ out += content.__class__.__name__
elif issubclass(field_type, models.ManyToManyField): elif issubclass(field_type, models.ManyToManyField):
out += '%d' % content.count() out += '%d' % content.count()
elif type(content) in (int, long): elif isinstance(content, six.integer_types):
out += unicode(content) out += str(content)
elif content is None: elif content is None:
out += 'None' out += 'None'
else: else:
txt = unicode(content) txt = str(content)
if len(txt) > self.polymorphic_showfield_max_field_width: if len(txt) > self.polymorphic_showfield_max_field_width:
txt = txt[:self.polymorphic_showfield_max_field_width - 2] + '..' txt = txt[:self.polymorphic_showfield_max_field_width - 2] + '..'
out += '"' + txt + '"' out += '"' + txt + '"'
@ -58,7 +58,7 @@ class ShowFieldBase(object):
# if this is the standard primary key named "id", print it as we did with older versions of django_polymorphic # if this is the standard primary key named "id", print it as we did with older versions of django_polymorphic
if field.primary_key and field.name == 'id' and type(field) == models.AutoField: if field.primary_key and field.name == 'id' and type(field) == models.AutoField:
out += ' ' + unicode(getattr(self, field.name)) out += ' ' + str(getattr(self, field.name))
# otherwise, display it just like all other fields (with correct type, shortened content etc.) # otherwise, display it just like all other fields (with correct type, shortened content etc.)
else: else:
@ -108,11 +108,11 @@ class ShowFieldBase(object):
indent = len(self.__class__.__name__) + 5 indent = len(self.__class__.__name__) + 5
indentstr = ''.rjust(indent) indentstr = ''.rjust(indent)
out = u'' out = ''
xpos = 0 xpos = 0
possible_line_break_pos = None possible_line_break_pos = None
for i in xrange(len(parts)): for i in range(len(parts)):
new_section, p, separator = parts[i] new_section, p, separator = parts[i]
final = (i == len(parts) - 1) final = (i == len(parts) - 1)
if not final: if not final:
@ -139,7 +139,7 @@ class ShowFieldBase(object):
if not new_section: if not new_section:
possible_line_break_pos = len(out) possible_line_break_pos = len(out)
return u'<' + out + '>' return '<' + out + '>'
class ShowFieldType(ShowFieldBase): class ShowFieldType(ShowFieldBase):

View File

@ -1,4 +1,5 @@
from django.template import Library, Node, TemplateSyntaxError from django.template import Library, Node, TemplateSyntaxError
from django.utils import six
register = Library() register = Library()
@ -31,7 +32,7 @@ class BreadcrumbScope(Node):
# Instead, have an assignment tag that inserts that in the template. # Instead, have an assignment tag that inserts that in the template.
base_opts = self.base_opts.resolve(context) base_opts = self.base_opts.resolve(context)
new_vars = {} new_vars = {}
if base_opts and not isinstance(base_opts, basestring): if base_opts and not isinstance(base_opts, six.string_types):
new_vars = { new_vars = {
'app_label': base_opts.app_label, # What this is all about 'app_label': base_opts.app_label, # What this is all about
'opts': base_opts, 'opts': base_opts,

View File

@ -7,13 +7,13 @@ 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_unicode
from django.utils import six
class UUIDVersionError(Exception): class UUIDVersionError(Exception):
pass pass
class UUIDField(models.CharField): class UUIDField(six.with_metaclass(models.SubfieldBase, models.CharField)):
"""Encode and stores a Python uuid.UUID in a manner that is appropriate """Encode and stores a Python uuid.UUID in a manner that is appropriate
for the given datatabase that we are using. for the given datatabase that we are using.
@ -22,7 +22,6 @@ class UUIDField(models.CharField):
This class supports type 1, 2, 4, and 5 UUID's. This class supports type 1, 2, 4, and 5 UUID's.
""" """
__metaclass__ = models.SubfieldBase
_CREATE_COLUMN_TYPES = { _CREATE_COLUMN_TYPES = {
'postgresql_psycopg2': 'uuid', 'postgresql_psycopg2': 'uuid',

View File

@ -29,6 +29,7 @@ setup(
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Software Development :: Libraries :: Python Modules',
] ]
) )