Fixed #18963 -- Used a subclass-friendly pattern

for Python 2 object model compatibility methods.
This commit is contained in:
Aymeric Augustin 2012-11-03 21:43:11 +01:00
parent 973f539ab8
commit fc10418fba
14 changed files with 61 additions and 50 deletions

View File

@ -18,7 +18,9 @@ class PermLookupDict(object):
def __bool__(self):
return self.user.has_module_perms(self.module_name)
__nonzero__ = __bool__ # Python 2
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
class PermWrapper(object):

View File

@ -151,7 +151,9 @@ class MeasureBase(object):
**{self.STANDARD_UNIT: (self.standard / other)})
else:
raise TypeError('%(class)s must be divided with number or %(class)s' % {"class":pretty_name(self)})
__div__ = __truediv__ # Python 2 compatibility
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
def __itruediv__(self, other):
if isinstance(other, NUMERIC_TYPES):
@ -159,11 +161,15 @@ class MeasureBase(object):
return self
else:
raise TypeError('%(class)s must be divided with number' % {"class":pretty_name(self)})
__idiv__ = __itruediv__ # Python 2 compatibility
def __idiv__(self, other): # Python 2 compatibility
return type(self).__itruediv__(self, other)
def __bool__(self):
return bool(self.standard)
__nonzero__ = __bool__ # Python 2 compatibility
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
def default_units(self, kwargs):
"""
@ -314,7 +320,9 @@ class Area(MeasureBase):
**{self.STANDARD_UNIT: (self.standard / other)})
else:
raise TypeError('%(class)s must be divided by a number' % {"class":pretty_name(self)})
__div__ = __truediv__ # Python 2 compatibility
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
# Shortcuts

View File

@ -28,7 +28,9 @@ class File(FileProxyMixin):
def __bool__(self):
return bool(self.name)
__nonzero__ = __bool__ # Python 2
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
def __len__(self):
return self.size
@ -142,7 +144,9 @@ class ContentFile(File):
def __bool__(self):
return True
__nonzero__ = __bool__ # Python 2
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
def open(self, mode=None):
self.seek(0)

View File

@ -112,7 +112,7 @@ class Serializer(object):
if callable(getattr(self.stream, 'getvalue', None)):
return self.stream.getvalue()
class Deserializer(object):
class Deserializer(six.Iterator):
"""
Abstract base deserializer class.
"""
@ -138,8 +138,6 @@ class Deserializer(object):
"""Iteration iterface -- return the next item in the stream"""
raise NotImplementedError
next = __next__ # Python 2 compatibility
class DeserializedObject(object):
"""
A deserialized model.

View File

@ -161,8 +161,6 @@ class Deserializer(base.Deserializer):
return self._handle_object(node)
raise StopIteration
next = __next__ # Python 2 compatibility
def _handle_object(self, node):
"""
Convert an <object> node to a DeserializedObject.

View File

@ -774,7 +774,7 @@ class FormatStylePlaceholderCursor(object):
return CursorIterator(self.cursor)
class CursorIterator(object):
class CursorIterator(six.Iterator):
"""Cursor iterator wrapper that invokes our custom row factory."""
@ -788,8 +788,6 @@ class CursorIterator(object):
def __next__(self):
return _rowfactory(next(self.iter), self.cursor)
next = __next__ # Python 2 compatibility
def _rowfactory(row, cursor):
# Cast numeric values as the appropriate Python type based upon the

View File

@ -62,7 +62,9 @@ class ExpressionNode(tree.Node):
def __truediv__(self, other):
return self._combine(other, self.DIV, False)
__div__ = __truediv__ # Python 2 compatibility
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
def __mod__(self, other):
return self._combine(other, self.MOD, False)
@ -94,7 +96,9 @@ class ExpressionNode(tree.Node):
def __rtruediv__(self, other):
return self._combine(other, self.DIV, True)
__rdiv__ = __rtruediv__ # Python 2 compatibility
def __rdiv__(self, other): # Python 2 compatibility
return type(self).__rtruediv__(self, other)
def __rmod__(self, other):
return self._combine(other, self.MOD, True)
@ -151,10 +155,10 @@ class DateModifierNode(ExpressionNode):
(A custom function is used in order to preserve six digits of fractional
second information on sqlite, and to format both date and datetime values.)
Note that microsecond comparisons are not well supported with MySQL, since
Note that microsecond comparisons are not well supported with MySQL, since
MySQL does not store microsecond information.
Only adding and subtracting timedeltas is supported, attempts to use other
Only adding and subtracting timedeltas is supported, attempts to use other
operations raise a TypeError.
"""
def __init__(self, children, connector, negated=False):

View File

@ -136,7 +136,9 @@ class QuerySet(object):
except StopIteration:
return False
return True
__nonzero__ = __bool__ # Python 2
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
def __contains__(self, val):
# The 'in' operator works without this method, due to __iter__. This

View File

@ -67,9 +67,9 @@ class BoundMethodWeakref(object):
same BoundMethodWeakref instance.
"""
_allInstances = weakref.WeakValueDictionary()
def __new__( cls, target, onDelete=None, *arguments,**named ):
"""Create new instance or return current instance
@ -92,7 +92,7 @@ class BoundMethodWeakref(object):
cls._allInstances[key] = base
base.__init__( target, onDelete, *arguments,**named)
return base
def __init__(self, target, onDelete=None):
"""Return a weak-reference-like instance for a bound method
@ -132,7 +132,7 @@ class BoundMethodWeakref(object):
self.weakFunc = weakref.ref(target.__func__, remove)
self.selfName = str(target.__self__)
self.funcName = str(target.__func__.__name__)
def calculateKey( cls, target ):
"""Calculate the reference key for this reference
@ -141,7 +141,7 @@ class BoundMethodWeakref(object):
"""
return (id(target.__self__),id(target.__func__))
calculateKey = classmethod( calculateKey )
def __str__(self):
"""Give a friendly representation of the object"""
return """%s( %s.%s )"""%(
@ -157,14 +157,16 @@ class BoundMethodWeakref(object):
def __bool__( self ):
"""Whether we are still a valid reference"""
return self() is not None
__nonzero__ = __bool__ # Python 2
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
def __eq__(self, other):
"""Compare with another reference"""
if not isinstance(other, self.__class__):
return self.__class__ == type(other)
return self.key == other.key
def __call__(self):
"""Return a strong reference to the bound method

View File

@ -69,7 +69,9 @@ class BaseFormSet(object):
def __bool__(self):
"""All formsets have a management form which is not included in the length"""
return True
__nonzero__ = __bool__ # Python 2
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
@property
def management_form(self):

View File

@ -256,7 +256,7 @@ class MultiPartParser(object):
"""Cleanup filename from Internet Explorer full paths."""
return filename and filename[filename.rfind("\\")+1:].strip()
class LazyStream(object):
class LazyStream(six.Iterator):
"""
The LazyStream wrapper allows one to get and "unget" bytes from a stream.
@ -323,8 +323,6 @@ class LazyStream(object):
self.position += len(output)
return output
next = __next__ # Python 2 compatibility
def close(self):
"""
Used to invalidate/disable this lazy stream.
@ -369,7 +367,7 @@ class LazyStream(object):
" if there is none, report this to the Django developers."
)
class ChunkIter(object):
class ChunkIter(six.Iterator):
"""
An iterable that will yield chunks of data. Given a file-like object as the
constructor, this object will yield chunks of read operations from that
@ -389,12 +387,10 @@ class ChunkIter(object):
else:
raise StopIteration()
next = __next__ # Python 2 compatibility
def __iter__(self):
return self
class InterBoundaryIter(object):
class InterBoundaryIter(six.Iterator):
"""
A Producer that will iterate over boundaries.
"""
@ -411,9 +407,7 @@ class InterBoundaryIter(object):
except InputStreamExhausted:
raise StopIteration()
next = __next__ # Python 2 compatibility
class BoundaryIter(object):
class BoundaryIter(six.Iterator):
"""
A Producer that is sensitive to boundaries.
@ -489,8 +483,6 @@ class BoundaryIter(object):
stream.unget(chunk[-rollback:])
return chunk[:-rollback]
next = __next__ # Python 2 compatibility
def _find_boundary(self, data, eof = False):
"""
Finds a multipart boundary in data.

View File

@ -23,7 +23,7 @@ class BadHeaderError(ValueError):
pass
class HttpResponseBase(object):
class HttpResponseBase(six.Iterator):
"""
An HTTP response base class with dictionary-accessed headers.
@ -218,8 +218,6 @@ class HttpResponseBase(object):
# Subclasses must define self._iterator for this function.
return self.make_bytes(next(self._iterator))
next = __next__ # Python 2 compatibility
# These methods partially implement the file-like object interface.
# See http://docs.python.org/lib/bltin-file-objects.html

View File

@ -73,7 +73,9 @@ class Node(object):
For truth value testing.
"""
return bool(self.children)
__nonzero__ = __bool__ # Python 2
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
def __contains__(self, other):
"""

View File

@ -278,15 +278,13 @@ Iterators
::
class MyIterator(object):
class MyIterator(six.Iterator):
def __iter__(self):
return self # implement some logic here
def __next__(self):
raise StopIteration # implement some logic here
next = __next__ # Python 2 compatibility
Boolean evaluation
~~~~~~~~~~~~~~~~~~
@ -297,7 +295,8 @@ Boolean evaluation
def __bool__(self):
return True # implement some logic here
__nonzero__ = __bool__ # Python 2 compatibility
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
Division
~~~~~~~~
@ -309,12 +308,14 @@ Division
def __truediv__(self, other):
return self / other # implement some logic here
__div__ = __truediv__ # Python 2 compatibility
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
def __itruediv__(self, other):
return self // other # implement some logic here
__idiv__ = __itruediv__ # Python 2 compatibility
def __idiv__(self, other): # Python 2 compatibility
return type(self).__itruediv__(self, other)
.. module: django.utils.six