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.
Please see LICENSE and AUTHORS for more information.
"""
from __future__ import absolute_import
import django
from polymorphic_model import PolymorphicModel
from manager import PolymorphicManager
from query import PolymorphicQuerySet
from query_translate import translate_polymorphic_Q_object
from showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
from showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility
from .polymorphic_model import PolymorphicModel
from .manager import PolymorphicManager
from .query import PolymorphicQuerySet
from .query_translate import translate_polymorphic_Q_object
from .showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
from .showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility
# 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.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
def get_for_model(self, model, for_concrete_model=True):
from django.utils.encoding import smart_unicode
if for_concrete_model:
model = model._meta.concrete_model
elif model._deferred:
@ -36,7 +35,7 @@ if django.VERSION[:2] < (1, 5):
ct, created = self.get_or_create(
app_label = opts.app_label,
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)

View File

@ -13,7 +13,8 @@ from django.core.urlresolvers import RegexURLResolver
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response
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.translation import ugettext_lazy as _
@ -315,7 +316,7 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
opts = self.model._meta
context = {
'title': _('Add %s') % force_unicode(opts.verbose_name),
'title': _('Add %s') % force_text(opts.verbose_name),
'adminform': adminForm,
'is_popup': "_popup" in request.REQUEST,
'media': mark_safe(media),
@ -482,7 +483,7 @@ class PolymorphicChildModelAdmin(admin.ModelAdmin):
# By not declaring the fields/form in the base class,
# get_form() will populate the form with all available fields.
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.
for fieldset in self.base_fieldsets:

View File

@ -2,6 +2,7 @@
""" PolymorphicModel Meta Class
Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/
"""
from __future__ import absolute_import
import sys
import inspect
@ -10,8 +11,8 @@ from django.db import models
from django.db.models.base import ModelBase
from django.db.models.manager import ManagerDescriptor
from manager import PolymorphicManager
from query import PolymorphicQuerySet
from .manager import PolymorphicManager
from .query import PolymorphicQuerySet
# PolymorphicQuerySet Q objects (and filter()) support these additional key words.
# 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
Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/
"""
from __future__ import unicode_literals
import warnings
from django.db import models
from polymorphic.query import PolymorphicQuerySet
@ -42,4 +43,4 @@ class PolymorphicManager(models.Manager):
return getattr(self.get_query_set(), name)
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.
Please see LICENSE and AUTHORS for more information.
"""
from __future__ import absolute_import
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django import VERSION as django_VERSION
from django.utils import six
from base import PolymorphicModelBase
from manager import PolymorphicManager
from query_translate import translate_polymorphic_Q_object
from .base import PolymorphicModelBase
from .manager import PolymorphicManager
from .query_translate import translate_polymorphic_Q_object
###################################################################################
### PolymorphicModel
class PolymorphicModel(models.Model):
class PolymorphicModel(six.with_metaclass(PolymorphicModelBase, models.Model)):
"""
Abstract base class that provides polymorphic behaviour
for any model directly or indirectly derived from it.
@ -44,7 +46,6 @@ class PolymorphicModel(models.Model):
super(YourClass,self).save(*args,**kwargs)
"""
__metaclass__ = PolymorphicModelBase
# for PolymorphicModelBase, so it can tell which models are polymorphic and which are not (duck typing)
polymorphic_model_marker = True
@ -168,7 +169,7 @@ class PolymorphicModel(models.Model):
subclasses_and_superclasses_accessors = self._get_inheritance_relation_fields_and_models()
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)
if type(orig_accessor) in [SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor]:
#print >>sys.stderr, '---------- replacing', name, orig_accessor, '->', model

View File

@ -2,14 +2,16 @@
""" QuerySet for PolymorphicModel
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.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_field_path
from .query_translate import translate_polymorphic_filter_definitions_in_kwargs, translate_polymorphic_filter_definitions_in_args
from .query_translate import translate_polymorphic_field_path
# chunk-size: maximum number of objects requested per db-request
# 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)"""
for a in args:
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)
def annotate(self, *args, **kwargs):
@ -207,12 +209,12 @@ class PolymorphicQuerySet(QuerySet):
real_object = transmogrify(real_class, real_object)
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)
setattr(real_object, anno_field_name, attr)
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)
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)
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:
real_object.polymorphic_annotate_names = annotate_names
# set polymorphic_extra_select_names in all objects (currently just used for debugging/printing)
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:
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):
try:
o = base_iter.next()
o = next(base_iter)
base_result_objects.append(o)
except StopIteration:
reached_end = True

View File

@ -2,11 +2,13 @@
""" PolymorphicQuerySet support functions
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.contrib.contenttypes.models import ContentType
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.
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:
return 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:
# 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)
assert model, 'PolymorphicModel: model %s (in app %s) not found!' % (model.__name__, appname)
if not issubclass(model, queryset_model):
@ -211,7 +213,7 @@ def _create_model_filter_Q(modellist, not_instance_of=False):
if not modellist:
return None
from polymorphic_model import PolymorphicModel
from .polymorphic_model import PolymorphicModel
if type(modellist) != list and type(modellist) != tuple:
if issubclass(modellist, PolymorphicModel):

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from django.db import models
from django.utils import six
class ShowFieldBase(object):
""" base class for the ShowField... model mixins, does the work """
@ -33,12 +33,12 @@ class ShowFieldBase(object):
out += content.__class__.__name__
elif issubclass(field_type, models.ManyToManyField):
out += '%d' % content.count()
elif type(content) in (int, long):
out += unicode(content)
elif isinstance(content, six.integer_types):
out += str(content)
elif content is None:
out += 'None'
else:
txt = unicode(content)
txt = str(content)
if len(txt) > self.polymorphic_showfield_max_field_width:
txt = txt[:self.polymorphic_showfield_max_field_width - 2] + '..'
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 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.)
else:
@ -108,11 +108,11 @@ class ShowFieldBase(object):
indent = len(self.__class__.__name__) + 5
indentstr = ''.rjust(indent)
out = u''
out = ''
xpos = 0
possible_line_break_pos = None
for i in xrange(len(parts)):
for i in range(len(parts)):
new_section, p, separator = parts[i]
final = (i == len(parts) - 1)
if not final:
@ -139,7 +139,7 @@ class ShowFieldBase(object):
if not new_section:
possible_line_break_pos = len(out)
return u'<' + out + '>'
return '<' + out + '>'
class ShowFieldType(ShowFieldBase):

View File

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

View File

@ -7,13 +7,13 @@ import uuid
from django import forms
from django.db import models
from django.utils.encoding import smart_unicode
from django.utils import six
class UUIDVersionError(Exception):
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
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.
"""
__metaclass__ = models.SubfieldBase
_CREATE_COLUMN_TYPES = {
'postgresql_psycopg2': 'uuid',

View File

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