PEP 8 cleaning

Conflicts:

	polymorphic/__init__.py
	polymorphic/polymorphic_model.py
fix_request_path_info
German M. Bravo 2011-11-26 00:22:18 -06:00 committed by Christopher Glass
parent c9922d8987
commit f987818fe4
9 changed files with 147 additions and 102 deletions

View File

@ -6,16 +6,16 @@ Copyright:
This code and affiliated files are (C) by Bert Constantin and individual contributors.
Please see LICENSE and AUTHORS for more information.
"""
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 showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility
VERSION = (1, 0 , 0, 'beta')
VERSION = (1, 0, 0, 'beta')
def get_version():
version = '%s.%s' % VERSION[0:2]
@ -23,4 +23,35 @@ def get_version():
version += '.%s' % VERSION[2]
if VERSION[3]:
version += ' %s' % VERSION[3]
return version
return version
# Proxied models need to have it's own ContentType
from django.contrib.contenttypes.models import ContentTypeManager
from django.utils.encoding import smart_unicode
def get_for_proxied_model(self, model):
"""
Returns the ContentType object for a given model, creating the
ContentType if necessary. Lookups are cached so that subsequent lookups
for the same model don't hit the database.
"""
opts = model._meta
key = (opts.app_label, opts.object_name.lower())
try:
ct = self.__class__._cache[self.db][key]
except KeyError:
# Load or create the ContentType entry. The smart_unicode() is
# needed around opts.verbose_name_raw because name_raw might be a
# django.utils.functional.__proxy__ object.
ct, created = self.get_or_create(
app_label=opts.app_label,
model=opts.object_name.lower(),
defaults={'name': smart_unicode(opts.verbose_name_raw)},
)
self._add_to_cache(self.db, ct)
return ct
ContentTypeManager.get_for_proxied_model = get_for_proxied_model

View File

@ -14,7 +14,7 @@ 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)
POLYMORPHIC_SPECIAL_Q_KWORDS = [ 'instance_of', 'not_instance_of']
POLYMORPHIC_SPECIAL_Q_KWORDS = ['instance_of', 'not_instance_of']
###################################################################################
@ -79,8 +79,8 @@ class PolymorphicModelBase(ModelBase):
# determine the name of the primary key field and store it into the class variable
# polymorphic_primary_key_name (it is needed by query.py)
for f in new_class._meta.fields:
if f.primary_key and type(f)!=models.OneToOneField:
new_class.polymorphic_primary_key_name=f.name
if f.primary_key and type(f) != models.OneToOneField:
new_class.polymorphic_primary_key_name = f.name
break
return new_class
@ -97,7 +97,7 @@ class PolymorphicModelBase(ModelBase):
if not issubclass(base, models.Model):
continue
if not getattr(base, 'polymorphic_model_marker', None):
continue # leave managers of non-polym. models alone
continue # leave managers of non-polym. models alone
for key, manager in base.__dict__.items():
if type(manager) == models.manager.ManagerDescriptor:
@ -113,7 +113,7 @@ class PolymorphicModelBase(ModelBase):
if manager._inherited:
continue # inherited managers (on the bases) have no significance, they are just copies
#print >>sys.stderr,'##',self.__name__, key
if isinstance(manager, PolymorphicManager): # validate any inherited polymorphic managers
if isinstance(manager, PolymorphicManager): # validate any inherited polymorphic managers
self.validate_model_manager(manager, self.__name__, key)
add_managers.append((base.__name__, key, manager))
add_managers_keys.add(key)
@ -148,7 +148,7 @@ class PolymorphicModelBase(ModelBase):
do_app_label_workaround = (meta
and model_module_name == 'polymorphic'
and model_name == 'PolymorphicModel'
and getattr(meta, 'app_label', None) is None )
and getattr(meta, 'app_label', None) is None)
if do_app_label_workaround:
meta.app_label = 'poly_dummy_app_label'
@ -162,7 +162,7 @@ class PolymorphicModelBase(ModelBase):
for f in self._meta.fields:
if f.name in POLYMORPHIC_SPECIAL_Q_KWORDS:
e = 'PolymorphicModel: "%s" - field name "%s" is not allowed in polymorphic models'
raise AssertionError(e % (self.__name__, f.name) )
raise AssertionError(e % (self.__name__, f.name))
@classmethod
def validate_model_manager(self, manager, model_name, manager_name):
@ -192,9 +192,9 @@ class PolymorphicModelBase(ModelBase):
_dumpdata_command_running = (sys.argv[1] == 'dumpdata')
def __getattribute__(self, name):
if name=='_default_manager':
if name == '_default_manager':
if self._dumpdata_command_running:
frm = inspect.stack()[1] # frm[1] is caller file name, frm[3] is caller function name
frm = inspect.stack()[1] # frm[1] is caller file name, frm[3] is caller function name
if 'django/core/management/commands/dumpdata.py' in frm[1]:
return self.base_objects
#caller_mod_name = inspect.getmodule(frm[0]).__name__ # does not work with python 2.4

View File

@ -20,36 +20,43 @@ except:
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()))
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)
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
@ -82,4 +89,3 @@ else:
assert ''.join(result) == s
assert result[1] == '' or result[1] is sep
return result

View File

@ -37,4 +37,3 @@ class PolymorphicManager(models.Manager):
def __unicode__(self):
return u'%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__)

View File

@ -12,7 +12,7 @@ http://bitbucket.org/bconstantin/django_polymorphic
Copyright:
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 django.db import models
@ -23,7 +23,7 @@ from base import PolymorphicModelBase
from manager import PolymorphicManager
from query_translate import translate_polymorphic_Q_object
###################################################################################
### PolymorphicModel
@ -31,18 +31,18 @@ class PolymorphicModel(models.Model):
"""
Abstract base class that provides polymorphic behaviour
for any model directly or indirectly derived from it.
For usage instructions & examples please see documentation.
PolymorphicModel declares one field for internal use (polymorphic_ctype)
and provides a polymorphic manager as the default manager
(and as 'objects').
PolymorphicModel overrides the save() and __init__ methods.
If your derived class overrides any of these methods as well, then you need
to take care that you correctly call the method of the superclass, like:
super(YourClass,self).save(*args,**kwargs)
"""
__metaclass__ = PolymorphicModelBase
@ -57,23 +57,23 @@ class PolymorphicModel(models.Model):
abstract = True
# avoid ContentType related field accessor clash (an error emitted by model validation)
# we really should use both app_label and model name, but this is only possible since Django 1.2
# we really should use both app_label and model name, but this is only possible since Django 1.2
if django_VERSION[0] <= 1 and django_VERSION[1] <= 1:
p_related_name_template = 'polymorphic_%(class)s_set'
else:
p_related_name_template = 'polymorphic_%(app_label)s.%(class)s_set'
polymorphic_ctype = models.ForeignKey(ContentType, null=True, editable=False,
related_name=p_related_name_template)
# some applications want to know the name of the fields that are added to its models
polymorphic_internal_model_fields = [ 'polymorphic_ctype' ]
polymorphic_internal_model_fields = ['polymorphic_ctype']
objects = PolymorphicManager()
base_objects = models.Manager()
@classmethod
def translate_polymorphic_Q_object(self_class,q):
return translate_polymorphic_Q_object(self_class,q)
def translate_polymorphic_Q_object(self_class, q):
return translate_polymorphic_Q_object(self_class, q)
def pre_save_polymorphic(self):
"""Normally not needed.
@ -96,18 +96,18 @@ class PolymorphicModel(models.Model):
"""Normally not needed.
If a non-polymorphic manager (like base_objects) has been used to
retrieve objects, then the real class/type of these objects may be
determined using this method."""
determined using this method."""
# the following line would be the easiest way to do this, but it produces sql queries
#return self.polymorphic_ctype.model_class()
# so we use the following version, which uses the CopntentType manager cache
return ContentType.objects.get_for_id(self.polymorphic_ctype_id).model_class()
def get_real_instance(self):
"""Normally not needed.
If a non-polymorphic manager (like base_objects) has been used to
retrieve objects, then the complete object with it's real class/type
and all fields may be retrieved with this method.
Each method call executes one db query (if necessary)."""
Each method call executes one db query (if necessary)."""
real_model = self.get_real_instance_class()
if real_model == self.__class__:
return self
@ -147,11 +147,11 @@ 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.iteritems():
orig_accessor = getattr(self.__class__, name, None)
if type(orig_accessor) in [SingleRelatedObjectDescriptor,ReverseSingleRelatedObjectDescriptor]:
#print >>sys.stderr, '---------- replacing',name, orig_accessor
setattr(self.__class__, name, property(create_accessor_function_for_model(model, name)) )
if type(orig_accessor) in [SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor]:
#print >>sys.stderr, '---------- replacing', name, orig_accessor, '->', model
setattr(self.__class__, name, property(create_accessor_function_for_model(model, name)))
def _get_inheritance_relation_fields_and_models(self):
"""helper function for __init__:
@ -167,8 +167,8 @@ class PolymorphicModel(models.Model):
if (issubclass(model, models.Model)
and model != models.Model
and model != self.__class__
and model != PolymorphicModel ):
add_model(model,as_ptr,result)
and model != PolymorphicModel):
add_model(model, as_ptr, result)
def add_all_super_models(model, result):
add_model_if_regular(model, True, result)
@ -180,6 +180,6 @@ class PolymorphicModel(models.Model):
add_model_if_regular(b, False, result)
result = {}
add_all_super_models(self.__class__,result)
add_all_sub_models(self.__class__,result)
add_all_super_models(self.__class__, result)
add_all_sub_models(self.__class__, result)
return result

View File

@ -60,13 +60,13 @@ class PolymorphicQuerySet(QuerySet):
def _filter_or_exclude(self, negate, *args, **kwargs):
"We override this internal Django functon as it is used for all filter member functions."
translate_polymorphic_filter_definitions_in_args(self.model, args) # the Q objects
additional_args = translate_polymorphic_filter_definitions_in_kwargs(self.model, kwargs) # filter_field='data'
translate_polymorphic_filter_definitions_in_args(self.model, args) # the Q objects
additional_args = translate_polymorphic_filter_definitions_in_kwargs(self.model, kwargs) # filter_field='data'
return super(PolymorphicQuerySet, self)._filter_or_exclude(negate, *(list(args) + additional_args), **kwargs)
def order_by(self, *args, **kwargs):
"""translate the field paths in the args, then call vanilla order_by."""
new_args = [ translate_polymorphic_field_path(self.model, a) for a in args ]
new_args = [translate_polymorphic_field_path(self.model, a) for a in args]
return super(PolymorphicQuerySet, self).order_by(*new_args, **kwargs)
def _process_aggregate_args(self, args, kwargs):
@ -170,12 +170,12 @@ class PolymorphicQuerySet(QuerySet):
# Then we copy the extra() select fields from the base objects to the real objects.
# TODO: defer(), only(): support for these would be around here
for modelclass, idlist in idlist_per_model.items():
qs = modelclass.base_objects.filter(pk__in=idlist) # use pk__in instead ####
qs.dup_select_related(self) # copy select related configuration to new qs
qs = modelclass.base_objects.filter(pk__in=idlist) # use pk__in instead ####
qs.dup_select_related(self) # copy select related configuration to new qs
for o in qs:
o_pk=getattr(o,pk_name)
o_pk = getattr(o, pk_name)
if self.query.aggregates:
for anno_field_name in self.query.aggregates.keys():
attr = getattr(base_result_objects_by_id[o_pk], anno_field_name)
@ -189,20 +189,20 @@ class PolymorphicQuerySet(QuerySet):
results[o_pk] = o
# re-create correct order and return result list
resultlist = [ results[ordered_id] for ordered_id in ordered_id_list if ordered_id in results ]
resultlist = [results[ordered_id] for ordered_id in ordered_id_list if ordered_id in results]
# 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 = self.query.aggregates.keys() # get annotate field list
for o in resultlist:
o.polymorphic_annotate_names=annotate_names
o.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 = self.query.extra_select.keys() # get extra select field list
for o in resultlist:
o.polymorphic_extra_select_names=extra_select_names
o.polymorphic_extra_select_names = extra_select_names
return resultlist
def iterator(self):
@ -250,14 +250,14 @@ class PolymorphicQuerySet(QuerySet):
def __repr__(self, *args, **kwargs):
if self.model.polymorphic_query_multiline_output:
result = [ repr(o) for o in self.all() ]
result = [repr(o) for o in self.all()]
return '[ ' + ',\n '.join(result) + ' ]'
else:
return super(PolymorphicQuerySet,self).__repr__(*args, **kwargs)
return super(PolymorphicQuerySet, self).__repr__(*args, **kwargs)
class _p_list_class(list):
def __repr__(self, *args, **kwargs):
result = [ repr(o) for o in self ]
result = [repr(o) for o in self]
return '[ ' + ',\n '.join(result) + ' ]'
def get_real_instances(self, base_result_objects=None):

View File

@ -47,6 +47,7 @@ def translate_polymorphic_filter_definitions_in_kwargs(queryset_model, kwargs):
return additional_args
def translate_polymorphic_Q_object(queryset_model, potential_q_object):
def tree_node_correct_field_specs(my_model, node):
" process all children of this Q node "
@ -68,6 +69,7 @@ def translate_polymorphic_Q_object(queryset_model, potential_q_object):
return potential_q_object
def translate_polymorphic_filter_definitions_in_args(queryset_model, args):
"""
Translate the non-keyword argument list for PolymorphicQuerySet.filter()
@ -104,7 +106,7 @@ def _translate_polymorphic_filter_definition(queryset_model, field_path, field_v
elif field_path == 'not_instance_of':
return _create_model_filter_Q(field_val, not_instance_of=True)
elif not '___' in field_path:
return None #no change
return None # no change
# filter expression contains '___' (i.e. filter for polymorphic field)
# => get the model class specified in the filter expression
@ -184,7 +186,7 @@ def translate_polymorphic_field_path(queryset_model, field_path):
newpath = '-'
else:
newpath = ''
newpath += basepath
if basepath:
newpath += '__'
@ -223,10 +225,9 @@ def _create_model_filter_Q(modellist, not_instance_of=False):
q = q | q_class_with_subclasses(subclass)
return q
qlist = [ q_class_with_subclasses(m) for m in modellist ]
qlist = [q_class_with_subclasses(m) for m in modellist]
q_ored = reduce(lambda a, b: a | b, qlist)
if not_instance_of:
q_ored = ~q_ored
return q_ored

View File

@ -2,10 +2,11 @@
from django.db import models
class ShowFieldBase(object):
""" base class for the ShowField... model mixins, does the work """
polymorphic_query_multiline_output = True # cause nicer multiline PolymorphicQuery output
polymorphic_query_multiline_output = True # cause nicer multiline PolymorphicQuery output
polymorphic_showfield_type = False
polymorphic_showfield_content = False
@ -32,14 +33,14 @@ class ShowFieldBase(object):
out += content.__class__.__name__
elif issubclass(field_type, models.ManyToManyField):
out += '%d' % content.count()
elif type(content) in (int,long):
elif type(content) in (int, long):
out += unicode(content)
elif content is None:
out += 'None'
else:
txt=unicode(content)
if len(txt)>self.polymorphic_showfield_max_field_width:
txt=txt[:self.polymorphic_showfield_max_field_width-2]+'..'
txt = unicode(content)
if len(txt) > self.polymorphic_showfield_max_field_width:
txt = txt[:self.polymorphic_showfield_max_field_width - 2] + '..'
out += '"' + txt + '"'
return out
@ -50,14 +51,14 @@ class ShowFieldBase(object):
if field.name in self.polymorphic_internal_model_fields or '_ptr' in field.name:
continue
if field.name in done_fields:
continue # work around django diamond inheritance problem
continue # work around django diamond inheritance problem
done_fields.add(field.name)
out = field.name
# 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))
if field.primary_key and field.name == 'id' and type(field) == models.AutoField:
out += ' ' + unicode(getattr(self, field.name))
# otherwise, display it just like all other fields (with correct type, shortened content etc.)
else:
@ -68,13 +69,13 @@ class ShowFieldBase(object):
out += ')'
if self.polymorphic_showfield_content:
out += self._showfields_get_content(field.name,type(field))
out += self._showfields_get_content(field.name, type(field))
parts.append((False, out,','))
parts.append((False, out, ','))
def _showfields_add_dynamic_fields(self, field_list, title, parts):
"helper for __unicode__"
parts.append( ( True, '- '+title, ':' ) )
parts.append((True, '- ' + title, ':'))
for field_name in field_list:
out = field_name
content = getattr(self, field_name)
@ -83,67 +84,74 @@ class ShowFieldBase(object):
if self.polymorphic_showfield_content:
out += self._showfields_get_content(field_name)
parts.append( ( False, out, ',' ) )
parts.append((False, out, ','))
def __unicode__(self):
# create list ("parts") containing one tuple for each title/field:
# ( bool: new section , item-text , separator to use after item )
# start with model name
parts = [ (True, self.__class__.__name__, ':') ]
parts = [(True, self.__class__.__name__, ':')]
# add all regular fields
self._showfields_add_regular_fields(parts)
# add annotate fields
if hasattr(self,'polymorphic_annotate_names'):
if hasattr(self, 'polymorphic_annotate_names'):
self._showfields_add_dynamic_fields(self.polymorphic_annotate_names, 'Ann', parts)
# add extra() select fields
if hasattr(self,'polymorphic_extra_select_names'):
if hasattr(self, 'polymorphic_extra_select_names'):
self._showfields_add_dynamic_fields(self.polymorphic_extra_select_names, 'Extra', parts)
# format result
indent = len(self.__class__.__name__)+5
indent = len(self.__class__.__name__) + 5
indentstr = ''.rjust(indent)
out=u''; xpos=0; possible_line_break_pos = None
out = u''
xpos = 0
possible_line_break_pos = None
for i in xrange(len(parts)):
new_section, p, separator = parts[i]
final = (i==len(parts)-1)
final = (i == len(parts) - 1)
if not final:
next_new_section, _, _ = parts[i+1]
next_new_section, _, _ = parts[i + 1]
if ( self.polymorphic_showfield_max_line_width
and xpos+len(p) > self.polymorphic_showfield_max_line_width
and possible_line_break_pos!=None ):
if (self.polymorphic_showfield_max_line_width
and xpos + len(p) > self.polymorphic_showfield_max_line_width
and possible_line_break_pos != None):
rest = out[possible_line_break_pos:]
out = out[:possible_line_break_pos]
out+= '\n'+indentstr+rest
xpos=indent+len(rest)
out += '\n' + indentstr + rest
xpos = indent + len(rest)
out += p; xpos += len(p)
out += p
xpos += len(p)
if not final:
if not next_new_section:
out += separator; xpos += len(separator)
out += ' '; xpos += 1
out += separator
xpos += len(separator)
out += ' '
xpos += 1
if not new_section:
possible_line_break_pos=len(out)
possible_line_break_pos = len(out)
return u'<'+out+'>'
return u'<' + out + '>'
class ShowFieldType(ShowFieldBase):
""" model mixin that shows the object's class and it's field types """
polymorphic_showfield_type = True
class ShowFieldContent(ShowFieldBase):
""" model mixin that shows the object's class, it's fields and field contents """
polymorphic_showfield_content = True
class ShowFieldTypeAndContent(ShowFieldBase):
""" model mixin, like ShowFieldContent, but also show field types """
polymorphic_showfield_type = True

View File

@ -4,15 +4,15 @@
import uuid
from django.forms.util import ValidationError
from django import forms
from django.db import models
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy
class UUIDVersionError(Exception):
pass
class UUIDField(models.CharField):
"""Encode and stores a Python uuid.UUID in a manner that is appropriate
for the given datatabase that we are using.
@ -60,24 +60,24 @@ class UUIDField(models.CharField):
self.auto = auto
self.version = version
if version==1:
if version == 1:
self.node, self.clock_seq = node, clock_seq
elif version==3 or version==5:
elif version == 3 or version == 5:
self.namespace, self.name = namespace, name
super(UUIDField, self).__init__(verbose_name=verbose_name,
name=name, **kwargs)
def create_uuid(self):
if not self.version or self.version==4:
if not self.version or self.version == 4:
return uuid.uuid4()
elif self.version==1:
elif self.version == 1:
return uuid.uuid1(self.node, self.clock_seq)
elif self.version==2:
elif self.version == 2:
raise UUIDVersionError("UUID version 2 is not supported.")
elif self.version==3:
elif self.version == 3:
return uuid.uuid3(self.namespace, self.name)
elif self.version==5:
elif self.version == 5:
return uuid.uuid5(self.namespace, self.name)
else:
raise UUIDVersionError("UUID version %s is not valid." % self.version)
@ -116,7 +116,7 @@ class UUIDField(models.CharField):
value = self.create_uuid()
setattr(model_instance, self.attname, value)
else:
value = super(UUIDField, self).pre_save(model_instance,add)
value = super(UUIDField, self).pre_save(model_instance, add)
if self.auto and not value:
value = self.create_uuid()
setattr(model_instance, self.attname, value)