# Test enhancements related to descriptors and new-style classes
from test
.test_support
import verify
, vereq
, verbose
, TestFailed
, TESTFN
, get_original_stdout
from copy
import deepcopy
warnings
.filterwarnings("ignore",
r
'complex divmod\(\), // and % are deprecated$',
DeprecationWarning, r
'(<string>|%s)$' % __name__
)
raise TestFailed
, "%r is %r" % (a
, b
)
def testunop(a
, res
, expr
="len(a)", meth
="__len__"):
if verbose
: print "checking", expr
vereq(eval(expr
, dict), res
)
while meth
not in t
.__dict
__:
vereq(m
, t
.__dict
__[meth
])
def testbinop(a
, b
, res
, expr
="a+b", meth
="__add__"):
if verbose
: print "checking", expr
# XXX Hack so this passes before 2.3 when -Qnew is specified.
if meth
== "__div__" and 1/2 == 0.5:
vereq(eval(expr
, dict), res
)
while meth
not in t
.__dict
__:
vereq(m
, t
.__dict
__[meth
])
def testternop(a
, b
, c
, res
, expr
="a[b:c]", meth
="__getslice__"):
if verbose
: print "checking", expr
dict = {'a': a
, 'b': b
, 'c': c
}
vereq(eval(expr
, dict), res
)
while meth
not in t
.__dict
__:
vereq(m
, t
.__dict
__[meth
])
def testsetop(a
, b
, res
, stmt
="a+=b", meth
="__iadd__"):
if verbose
: print "checking", stmt
dict = {'a': deepcopy(a
), 'b': b
}
while meth
not in t
.__dict
__:
vereq(m
, t
.__dict
__[meth
])
bm
= getattr(dict['a'], meth
)
def testset2op(a
, b
, c
, res
, stmt
="a[b]=c", meth
="__setitem__"):
if verbose
: print "checking", stmt
dict = {'a': deepcopy(a
), 'b': b
, 'c': c
}
while meth
not in t
.__dict
__:
vereq(m
, t
.__dict
__[meth
])
bm
= getattr(dict['a'], meth
)
def testset3op(a
, b
, c
, d
, res
, stmt
="a[b:c]=d", meth
="__setslice__"):
if verbose
: print "checking", stmt
dict = {'a': deepcopy(a
), 'b': b
, 'c': c
, 'd': d
}
while meth
not in t
.__dict
__:
vereq(m
, t
.__dict
__[meth
])
bm
= getattr(dict['a'], meth
)
vereq(Classic
.__doc
__, "A classic docstring.")
vereq(Classic
.__dict
__['__doc__'], "A classic docstring.")
verify(Classic2
.__doc__
is None)
vereq(NewStatic
.__doc
__, "Another docstring.")
vereq(NewStatic
.__dict
__['__doc__'], "Another docstring.")
class NewStatic2(object):
verify(NewStatic2
.__doc__
is None)
class NewDynamic(object):
vereq(NewDynamic
.__doc
__, "Another docstring.")
vereq(NewDynamic
.__dict
__['__doc__'], "Another docstring.")
class NewDynamic2(object):
verify(NewDynamic2
.__doc__
is None)
if verbose
: print "Testing list operations..."
testbinop([1], [2], [1,2], "a+b", "__add__")
testbinop([1,2,3], 2, 1, "b in a", "__contains__")
testbinop([1,2,3], 4, 0, "b in a", "__contains__")
testbinop([1,2,3], 1, 2, "a[b]", "__getitem__")
testternop([1,2,3], 0, 2, [1,2], "a[b:c]", "__getslice__")
testsetop([1], [2], [1,2], "a+=b", "__iadd__")
testsetop([1,2], 3, [1,2,1,2,1,2], "a*=b", "__imul__")
testunop([1,2,3], 3, "len(a)", "__len__")
testbinop([1,2], 3, [1,2,1,2,1,2], "a*b", "__mul__")
testbinop([1,2], 3, [1,2,1,2,1,2], "b*a", "__rmul__")
testset2op([1,2], 1, 3, [1,3], "a[b]=c", "__setitem__")
testset3op([1,2,3,4], 1, 3, [5,6], [1,5,6,4], "a[b:c]=d", "__setslice__")
if verbose
: print "Testing dict operations..."
testbinop({1:2}, {2:1}, -1, "cmp(a,b)", "__cmp__")
testbinop({1:2,3:4}, 1, 1, "b in a", "__contains__")
testbinop({1:2,3:4}, 2, 0, "b in a", "__contains__")
testbinop({1:2,3:4}, 1, 2, "a[b]", "__getitem__")
for i
in d
.keys(): l1
.append(i
)
for i
in iter(d
): l
.append(i
)
for i
in d
.__iter
__(): l
.append(i
)
for i
in dict.__iter
__(d
): l
.append(i
)
testunop(d
, 2, "len(a)", "__len__")
vereq(eval(repr(d
), {}), d
)
vereq(eval(d
.__repr
__(), {}), d
)
testset2op({1:2,3:4}, 2, 3, {1:2,2:3,3:4}, "a[b]=c", "__setitem__")
print "Testing dict constructor ..."
d
= dict({1: 2, 'a': 'b'})
vereq(d
, {1: 2, 'a': 'b'})
vereq(d
, dict(d
.items()))
vereq(d
, dict(d
.iteritems()))
d
= dict({'one':1, 'two':2})
vereq(d
, dict(one
=1, two
=2))
vereq(d
, dict({"one": 1}, two
=2))
vereq(d
, dict([("two", 2)], one
=1))
vereq(d
, dict([("one", 100), ("two", 200)], **d
))
verify(d
is not dict(**d
))
for badarg
in 0, 0L, 0j
, "0", [0], (0,):
# It's a sequence, and its elements are also sequences (gotta
# love strings <wink>), but they aren't of length 2, so this
# one seemed better as a ValueError than a TypeError.
raise TestFailed("no TypeError from dict(%r)" % badarg
)
raise TestFailed("no TypeError from dict(%r)" % badarg
)
raise TestFailed("no TypeError from dict({}, {})")
# Lacks a .keys() method; will be added later.
dict = {1:2, 3:4, 'a':1j
}
raise TestFailed("no TypeError from dict(incomplete mapping)")
Mapping
.keys
= lambda self
: self
.dict.keys()
Mapping
.__getitem
__ = lambda self
, i
: self
.dict[i
]
# Init from sequence of iterable objects, each producing a 2-sequence.
def __init__(self
, first
, last
):
return iter([self
.first
, self
.last
])
d
= dict([AddressBookEntry('Tim', 'Warsaw'),
AddressBookEntry('Barry', 'Peters'),
AddressBookEntry('Tim', 'Peters'),
AddressBookEntry('Barry', 'Warsaw')])
vereq(d
, {'Barry': 'Warsaw', 'Tim': 'Peters'})
d
= dict(zip(range(4), range(1, 5)))
vereq(d
, dict([(i
, i
+1) for i
in range(4)]))
for bad
in [('tooshort',)], [('too', 'long', 'by 1')]:
raise TestFailed("no ValueError from dict(%r)" % bad
)
print "Testing dir() ..."
# Just make sure these don't blow up!
for arg
in 2, 2L, 2j
, 2e0
, [2], "2", u
"2", (2,), {2:2}, type, test_dir
:
cstuff
= ['Cdata', 'Cmethod', '__doc__', '__module__']
verify('im_self' in dir(C
.Cmethod
))
c
= C() # c.__doc__ is an odd thing to see here; ditto c.__module__.
c
.cmethod
= lambda self
: 0
vereq(dir(c
), cstuff
+ ['cdata', 'cmethod'])
verify('im_self' in dir(c
.Cmethod
))
astuff
= ['Adata', 'Amethod'] + cstuff
verify('im_self' in dir(A
.Amethod
))
verify('im_self' in dir(a
.Amethod
))
a
.amethod
= lambda self
: 3
vereq(dir(a
), astuff
+ ['adata', 'amethod'])
# The same, but with new-style classes. Since these have object as a
# base class, a lot more gets sucked in.
def interesting(strings
):
return [s
for s
in strings
if not s
.startswith('_')]
cstuff
= ['Cdata', 'Cmethod']
vereq(interesting(dir(C
)), cstuff
)
vereq(interesting(dir(c
)), cstuff
)
verify('im_self' in dir(C
.Cmethod
))
c
.cmethod
= lambda self
: 0
vereq(interesting(dir(c
)), cstuff
+ ['cdata', 'cmethod'])
verify('im_self' in dir(c
.Cmethod
))
astuff
= ['Adata', 'Amethod'] + cstuff
vereq(interesting(dir(A
)), astuff
)
verify('im_self' in dir(A
.Amethod
))
vereq(interesting(dir(a
)), astuff
)
a
.amethod
= lambda self
: 3
vereq(interesting(dir(a
)), astuff
+ ['adata', 'amethod'])
verify('im_self' in dir(a
.Amethod
))
names
= [x
for x
in dir(minstance
) if x
not in ["__name__", "__doc__"]]
__dict__
= property(getdict
)
vereq(m2instance
.__dict
__, "Not a dict!")
# Two essentially featureless objects, just inheriting stuff from
vereq(dir(None), dir(Ellipsis))
# Nasty test case for proxied objects
return "Wrapper(%s)" % repr(self
.__obj
)
def __getitem__(self
, key
):
return Wrapper(self
.__obj
[key
])
def __getattr__(self
, name
):
return Wrapper(getattr(self
.__obj
, name
))
return Wrapper(type(self
))
__class__
= property(__getclass
)
dir(C()) # This used to segfault
for name
, expr
in binops
.items():
for name
, expr
in unops
.items():
def numops(a
, b
, skip
=[]):
for name
, expr
in binops
.items():
testbinop(a
, b
, res
, expr
, name
)
for name
, expr
in unops
.items():
testunop(a
, res
, expr
, name
)
if verbose
: print "Testing int operations..."
# The following crashes in Python 2.2
vereq((1).__nonzero
__(), 1)
vereq((0).__nonzero
__(), 0)
# This returns 'NotImplemented' in Python 2.2
def __add__(self
, other
):
raise TestFailed
, "NotImplemented should have caused TypeError"
raise TestFailed
, "should have raised OverflowError"
if verbose
: print "Testing long operations..."
if verbose
: print "Testing float operations..."
if verbose
: print "Testing complex operations..."
numops(100.0j
, 3.0j
, skip
=['lt', 'le', 'gt', 'ge', 'int', 'long', 'float'])
def __new__(cls
, *args
, **kwds
):
result
= complex.__new
__(cls
, *args
)
result
.prec
= kwds
.get('prec', 12)
return "%.*g" % (prec
, self
.real
)
return "%.*gj" % (prec
, self
.imag
)
return "(%.*g+%.*gj)" % (prec
, self
.real
, prec
, self
.imag
)
if verbose
: print "Testing spamlist operations..."
import copy
, xxsubtype
as spam
def spamlist(l
, memo
=None):
copy
._deepcopy
_dispatch
[spam
.spamlist
] = spamlist
testbinop(spamlist([1]), spamlist([2]), spamlist([1,2]), "a+b", "__add__")
testbinop(spamlist([1,2,3]), 2, 1, "b in a", "__contains__")
testbinop(spamlist([1,2,3]), 4, 0, "b in a", "__contains__")
testbinop(spamlist([1,2,3]), 1, 2, "a[b]", "__getitem__")
testternop(spamlist([1,2,3]), 0, 2, spamlist([1,2]),
"a[b:c]", "__getslice__")
testsetop(spamlist([1]), spamlist([2]), spamlist([1,2]),
testsetop(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "a*=b", "__imul__")
testunop(spamlist([1,2,3]), 3, "len(a)", "__len__")
testbinop(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "a*b", "__mul__")
testbinop(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "b*a", "__rmul__")
testset2op(spamlist([1,2]), 1, 3, spamlist([1,3]), "a[b]=c", "__setitem__")
testset3op(spamlist([1,2,3,4]), 1, 3, spamlist([5,6]),
spamlist([1,5,6,4]), "a[b:c]=d", "__setslice__")
if verbose
: print "Testing spamdict operations..."
import copy
, xxsubtype
as spam
def spamdict(d
, memo
=None):
for k
, v
in d
.items(): sd
[k
] = v
copy
._deepcopy
_dispatch
[spam
.spamdict
] = spamdict
testbinop(spamdict({1:2}), spamdict({2:1}), -1, "cmp(a,b)", "__cmp__")
testbinop(spamdict({1:2,3:4}), 1, 1, "b in a", "__contains__")
testbinop(spamdict({1:2,3:4}), 2, 0, "b in a", "__contains__")
testbinop(spamdict({1:2,3:4}), 1, 2, "a[b]", "__getitem__")
for i
in d
.keys(): l1
.append(i
)
for i
in iter(d
): l
.append(i
)
for i
in d
.__iter
__(): l
.append(i
)
for i
in type(spamdict({})).__iter
__(d
): l
.append(i
)
spamd
= spamdict(straightd
)
testunop(spamd
, 2, "len(a)", "__len__")
testunop(spamd
, repr(straightd
), "repr(a)", "__repr__")
testset2op(spamdict({1:2,3:4}), 2, 3, spamdict({1:2,2:3,3:4}),
vereq(a
.items(), [('foo', 'bar')])
if verbose
: print "Testing Python subclass of dict..."
verify(issubclass(dict, dict))
verify(isinstance({}, dict))
verify(d
.__class
__ is dict)
verify(isinstance(d
, dict))
def __init__(self
, *a
, **kw
):
for k
, v
in kw
.items(): self
[v
] = k
def __getitem__(self
, key
):
def __setitem__(self
, key
, value
):
verify(isinstance(key
, type(0)))
dict.__setitem
__(self
, key
, value
)
def setstate(self
, state
):
verify(issubclass(C
, dict))
vereq(a2
[1] == 'foo' and a2
[2], 'bar')
if verbose
: print "pydict stress test ..."
if verbose
: print "Testing Python subclass of list..."
def __getitem__(self
, i
):
return list.__getitem
__(self
, i
) + 100
def __getslice__(self
, i
, j
):
vereq(a
[100:200], (100,200))
if verbose
: print "Testing __metaclass__..."
def setstate(self
, state
):
class __metaclass__(type):
def myself(cls
): return cls
def __new__(cls
, name
, bases
, dict):
return type.__new
__(cls
, name
, bases
, dict)
def __new__(cls
, name
, bases
, dict):
self
= object.__new
__(cls
)
__new__
= staticmethod(__new__
)
# Early binding of methods
setattr(it
, key
, self
.dict[key
].__get
__(it
, self
))
# More metaclass examples
# Automatically add __super to the class
# This trick only works for dynamic classes
def __new__(metaclass
, name
, bases
, dict):
cls
= super(autosuper
, metaclass
).__new
__(metaclass
,
# Name mangling for __super removes leading underscores
name
= "_%s__super" % name
setattr(cls
, name
, super(cls
))
__metaclass__
= autosuper
return "B" + self
.__super
.meth()
return "C" + self
.__super
.meth()
return "D" + self
.__super
.meth()
vereq(D().meth(), "DCBA")
return "E" + self
.__super
.meth()
vereq(E().meth(), "EBCA")
class autoproperty(type):
# Automatically create property attributes when methods
# named _get_x and/or _set_x are found
def __new__(metaclass
, name
, bases
, dict):
for key
, val
in dict.iteritems():
if key
.startswith("_get_"):
get
, set = hits
.get(key
, (None, None))
elif key
.startswith("_set_"):
get
, set = hits
.get(key
, (None, None))
for key
, (get
, set) in hits
.iteritems():
dict[key
] = property(get
, set)
return super(autoproperty
, metaclass
).__new
__(metaclass
,
__metaclass__
= autoproperty
verify(not hasattr(a
, "x"))
class multimetaclass(autoproperty
, autosuper
):
# Merge of multiple cooperating metaclasses
__metaclass__
= multimetaclass
return "B" + self
.__super
._get
_x
()
return "C" + self
.__super
._get
_x
()
return "D" + self
.__super
._get
_x
()
# Make sure type(x) doesn't call x.__class__.__init__
def __init__(self
, *args
):
else: raise TestFailed
, "calling object w/o call method should raise TypeError"
if verbose
: print "Testing Python subclass of module..."
def __init__(self
, name
):
def __getattribute__(self
, name
):
log
.append(("getattr", name
))
return MT
.__getattribute
__(self
, name
)
def __setattr__(self
, name
, value
):
log
.append(("setattr", name
, value
))
MT
.__setattr
__(self
, name
, value
)
def __delattr__(self
, name
):
log
.append(("delattr", name
))
MT
.__delattr
__(self
, name
)
vereq(log
, [("setattr", "foo", 12),
if verbose
: print "Testing multiple inheritance..."
def setstate(self
, state
):
vereq(d
.items(), [("hello", "world")])
vereq(d
["hello"], "world")
vereq(D
.__mro
__, (D
, dict, C
, object))
vereq(Node().__int
__(), 23)
vereq(Frag().__int
__(), 42)
# MI mixing classic and new-style classes.
# Classic MRO is preserved for a classic base class.
vereq(E
.__mro
__, (E
, D
, B
, A
, C
, object))
# But with a mix of classic bases, their MROs are combined using
vereq(F
.__mro
__, (F
, B
, C
, A
, object))
vereq(M1
.__mro__
, (M1
, C
, object))
vereq(m
.cmethod(), "C a")
vereq(m
.m1method(), "M1 a")
vereq(m
.all_method(), "M1 b")
vereq(M2
.__mro__
, (M2
, D
, C
, object))
vereq(m
.cmethod(), "C a")
vereq(m
.dmethod(), "D a")
vereq(m
.m2method(), "M2 a")
vereq(m
.all_method(), "M2 b")
class M3(M1
, M2
, object):
vereq(M3
.__mro__
, (M3
, M1
, M2
, D
, C
, object))
vereq(m
.cmethod(), "C a")
vereq(m
.dmethod(), "D a")
vereq(m
.m1method(), "M1 a")
vereq(m
.m2method(), "M2 a")
vereq(m
.m3method(), "M3 a")
vereq(m
.all_method(), "M3 b")
raise TestFailed
, "new class with only classic bases - shouldn't be"
if verbose
: print "Testing multiple inheritance special cases..."
def spam(self
): return "A"
def boo(self
): return "B"
def spam(self
): return "B"
def boo(self
): return "C"
vereq(D
.__mro
__, (D
, B
, C
, A
, object))
vereq(E
.__mro
__, (E
, C
, B
, A
, object))
raise TestFailed
, "expected MRO order disagreement (F)"
raise TestFailed
, "expected MRO order disagreement (G)"
# see thread python-dev/2002-October/029035.html
if verbose
: print "Testing ex5 from C3 switch discussion..."
vereq(Z
.__mro
__, (Z
, X
, B
, Y
, A
, C
, object))
# see "A Monotonic Superclass Linearization for Dylan",
# by Kim Barrett et al. (OOPSLA 1996)
if verbose
: print "Testing MRO monotonicity..."
class DayBoat(Boat
): pass
class WheelBoat(Boat
): pass
class EngineLess(DayBoat
): pass
class SmallMultihull(DayBoat
): pass
class PedalWheelBoat(EngineLess
,WheelBoat
): pass
class SmallCatamaran(SmallMultihull
): pass
class Pedalo(PedalWheelBoat
,SmallCatamaran
): pass
vereq(PedalWheelBoat
.__mro
__,
(PedalWheelBoat
, EngineLess
, DayBoat
, WheelBoat
, Boat
,
vereq(SmallCatamaran
.__mro
__,
(SmallCatamaran
, SmallMultihull
, DayBoat
, Boat
, object))
(Pedalo
, PedalWheelBoat
, EngineLess
, SmallCatamaran
,
SmallMultihull
, DayBoat
, WheelBoat
, Boat
, object))
# see "A Monotonic Superclass Linearization for Dylan",
# by Kim Barrett et al. (OOPSLA 1996)
def consistency_with_epg():
if verbose
: print "Testing consistentcy with EPG..."
class ScrollingMixin(object): pass
class EditingMixin(object): pass
class ScrollablePane(Pane
,ScrollingMixin
): pass
class EditablePane(Pane
,EditingMixin
): pass
class EditableScrollablePane(ScrollablePane
,EditablePane
): pass
vereq(EditableScrollablePane
.__mro
__,
(EditableScrollablePane
, ScrollablePane
, EditablePane
,
Pane
, ScrollingMixin
, EditingMixin
, object))
mro_err_msg
= """Cannot create a consistent method resolution
order (MRO) for bases """
if verbose
: print "Testing error messages for MRO disagreement..."
def raises(exc
, expected
, callable, *args
):
if not str(msg
).startswith(expected
):
raise TestFailed
, "Message %r, expected %r" % (str(msg
),
raise TestFailed
, "Expected %s" % exc
# Test some very simple errors
raises(TypeError, "duplicate base class A",
raises(TypeError, mro_err_msg
,
raises(TypeError, mro_err_msg
,
type, "X", (A
, C
, B
), {})
# Test a slightly more complex error
class GridLayout(object): pass
class HorizontalGrid(GridLayout
): pass
class VerticalGrid(GridLayout
): pass
class HVGrid(HorizontalGrid
, VerticalGrid
): pass
class VHGrid(VerticalGrid
, HorizontalGrid
): pass
raises(TypeError, mro_err_msg
,
type, "ConfusedGrid", (HVGrid
, VHGrid
), {})
if verbose
: print "Testing object class..."
vereq(a
.__class
__, object)
verify(not hasattr(a
, "foo"))
except (AttributeError, TypeError):
verify(0, "object() should not allow setting a foo attribute")
verify(not hasattr(object(), "__dict__"))
vereq(x
.__dict
__, {'foo': 1})
if verbose
: print "Testing __slots__..."
verify(not hasattr(x
, "__dict__"))
verify(not hasattr(x
, "foo"))
verify(not hasattr(x
, "__dict__"))
verify(not hasattr(x
, "a"))
verify(not hasattr(x
, "a"))
__slots__
= ['a', 'b', 'c']
verify(not hasattr(x
, "__dict__"))
verify(not hasattr(x
, 'a'))
verify(not hasattr(x
, 'b'))
verify(not hasattr(x
, 'c'))
"""Validate name mangling"""
def __init__(self
, value
):
verify(not hasattr(x
, '__dict__'))
verify(not hasattr(x
, '__a'))
raise TestFailed
, "Double underscored names not mangled"
# Make sure slot names are proper identifiers
raise TestFailed
, "[None] slots not caught"
raise TestFailed
, "['foo bar'] slots not caught"
raise TestFailed
, "['foo\\0bar'] slots not caught"
raise TestFailed
, "['1'] slots not caught"
raise TestFailed
, "[''] slots not caught"
__slots__
= ["a", "a_b", "_a", "A0123456789Z"]
counter
= 0 # counts the number of instances alive
__slots__
= ['a', 'b', 'c']
vereq(Counted
.counter
, 3)
vereq(Counted
.counter
, 0)
vereq(Counted
.counter
, 2)
vereq(Counted
.counter
, 0)
vereq(Counted
.counter
, 3)
vereq(Counted
.counter
, 0)
# Test cyclical leaks [SF bug 519621]
vereq(Counted
.counter
, 1)
vereq(Counted
.counter
, 0)
# Test lookup leaks [SF bug 572567]
def __cmp__(self
, other
):
orig_objects
= len(gc
.get_objects())
new_objects
= len(gc
.get_objects())
vereq(orig_objects
, new_objects
)
if verbose
: print "Testing __dict__ and __weakref__ in __slots__..."
verify(hasattr(a
, "__dict__"))
verify(not hasattr(a
, "__weakref__"))
vereq(a
.__dict
__, {"foo": 42})
__slots__
= ["__weakref__"]
verify(hasattr(a
, "__weakref__"))
verify(not hasattr(a
, "__dict__"))
raise TestFailed
, "shouldn't be allowed to set a.foo"
verify(hasattr(a
, "__dict__"))
verify(hasattr(a
, "__weakref__"))
vereq(a
.__dict
__, {"foo": 42})
verify(hasattr(a
, "__dict__"))
verify(hasattr(a
, "__weakref__"))
vereq(a
.__dict
__, {"foo": 42})
if verbose
: print "Testing class attribute propagation..."
# Test that dynamic attributes are inherited
verify(not hasattr(a
, "foobar"))
C
.method
= lambda self
: 42
C
.__repr
__ = lambda self
: "C()"
C
.__int
__ = lambda self
: 100
verify(not hasattr(a
, "spam"))
def mygetattr(self
, name
):
C
.__getattr
__ = mygetattr
def mysetattr(self
, name
, value
):
return object.__setattr
__(self
, name
, value
)
C
.__setattr
__ = mysetattr
verify(0, "expected AttributeError")
# Test handling of int*seq and seq*int
# Test handling of long*seq and seq*long
# Test comparison of classes with dynamic metaclasses
class dynamicmetaclass(type):
__metaclass__
= dynamicmetaclass
verify(someclass
!= object)
if verbose
: print "Testing errors..."
verify(0, "inheritance from both list and dict should be illegal")
verify(0, "inheritance from non-type should be illegal")
verify(0, "inheritance from CFunction should be illegal")
verify(0, "__slots__ = 1 should be illegal")
verify(0, "__slots__ = [1] should be illegal")
if verbose
: print "Testing class methods..."
vereq(D
.foo(d
, 1), (d
, 1))
# Test for a specific crash (SF bug 528132)
def f(cls
, arg
): return (cls
, arg
)
vereq(ff
.__get
__(0, int)(42), (int, 42))
vereq(ff
.__get
__(0)(42), (int, 42))
# Test super() with classmethods (SF bug 535444)
veris(super(D
,D
).goo
.im_self
, D
)
veris(super(D
,d
).goo
.im_self
, D
)
vereq(super(D
,D
).goo(), (D
,))
vereq(super(D
,d
).goo(), (D
,))
# Verify that argument is checked for callability (SF bug 753451)
classmethod(1).__get
__(1)
raise TestFailed
, "classmethod should check for callability"
if verbose
: print "Testing C-based class methods..."
x
, a1
, d1
= spam
.spamlist
.classmeth(*a
, **d
)
x
, a1
, d1
= spam
.spamlist().classmeth(*a
, **d
)
if verbose
: print "Testing static methods..."
vereq(D
.foo(d
, 1), (d
, 1))
def staticmethods_in_c():
if verbose
: print "Testing C-based static methods..."
x
, a1
, d1
= spam
.spamlist
.staticmeth(*a
, **d
)
x
, a1
, d2
= spam
.spamlist().staticmeth(*a
, **d
)
if verbose
: print "Testing classic classes..."
vereq(D
.foo(d
, 1), (d
, 1))
class E
: # *not* subclassing from C
vereq(E().foo
, C
.foo
) # i.e., unbound
verify(repr(C
.foo
.__get
__(C())).startswith("<bound method "))
if verbose
: print "Testing computed attributes..."
class computed_attribute(object):
def __init__(self
, get
, set=None, delete
=None):
def __get__(self
, obj
, type=None):
def __set__(self
, obj
, value
):
return self
.__set
(obj
, value
)
def __delete__(self
, obj
):
return self
.__delete
(obj
)
x
= computed_attribute(__get_x
, __set_x
, __delete_x
)
vereq(hasattr(a
, 'x'), 0)
if verbose
: print "Testing __new__ slot override..."
if verbose
: print "Testing mro() and overriding it..."
vereq(D
.mro(), [D
, B
, C
, A
, object])
vereq(D
.__mro
__, (D
, B
, C
, A
, object))
class PerverseMetaType(type):
__metaclass__
= PerverseMetaType
vereq(X
.__mro
__, (object, A
, C
, B
, D
, X
))
if verbose
: print "Testing operator overloading..."
"Intermediate class because object doesn't have a __setattr__"
def __getattr__(self
, name
):
def __setattr__(self
, name
, value
):
self
.setattr = (name
, value
)
return B
.__setattr
__(self
, name
, value
)
def __delattr__(self
, name
):
return B
.__delattr
__(self
, name
)
def __getitem__(self
, key
):
def __setitem__(self
, key
, value
):
self
.setitem
= (key
, value
)
def __delitem__(self
, key
):
def __getslice__(self
, i
, j
):
return ("getslice", i
, j
)
def __setslice__(self
, i
, j
, value
):
self
.setslice
= (i
, j
, value
)
def __delslice__(self
, i
, j
):
vereq(a
.foo
, ("getattr", "foo"))
vereq(a
.setattr, ("foo", 12))
vereq(a
[12], ("getitem", 12))
vereq(a
.setitem
, (12, 21))
vereq(a
[0:10], ("getslice", 0, 10))
vereq(a
.setslice
, (0, 10, "foo"))
vereq(a
.delslice
, (0, 10))
if verbose
: print "Testing methods..."
vereq(E().foo
, C
.foo
) # i.e., unbound
verify(repr(C
.foo
.__get
__(C(1))).startswith("<bound method "))
# Test operators like __hash__ for which a built-in default exists
if verbose
: print "Testing special operators..."
# Test the default behavior for static classes
def __getitem__(self
, i
):
vereq(cmp(c1
, c2
), cmp(id(c1
), id(c2
)))
# Note that the module name appears in str/repr, and that varies
# depending on whether this test is run standalone or from a framework.
verify(str(c1
).find('C object at ') >= 0)
# Test the default behavior for dynamic classes
def __getitem__(self
, i
):
vereq(cmp(d1
, d2
), cmp(id(d1
), id(d2
)))
# Note that the module name appears in str/repr, and that varies
# depending on whether this test is run standalone or from a framework.
verify(str(d1
).find('D object at ') >= 0)
# Test overridden behavior for static classes
def __cmp__(self
, other
):
return cmp(self
.x
, other
.x
)
return "Proxy:%s" % self
.x
return "Proxy(%r)" % self
.x
def __contains__(self
, value
):
vereq(str(p0
), "Proxy:0")
vereq(repr(p0
), "Proxy(0)")
# Test overridden behavior for dynamic classes
def __cmp__(self
, other
):
return cmp(self
.x
, other
.x
)
return "DProxy:%s" % self
.x
return "DProxy(%r)" % self
.x
def __contains__(self
, value
):
vereq(str(p0
), "DProxy:0")
vereq(repr(p0
), "DProxy(0)")
# Safety test for __cmp__
a
.__class
__.__cmp
__(a
, b
)
raise TestFailed
, "shouldn't allow %s.__cmp__(%r, %r)" % (
def __new__(cls
, letter
):
return str.__new
__(cls
, letter
)
# sys.stdout needs to be the original to trigger the recursion bug
sys
.stdout
= get_original_stdout()
# nothing should actually be printed, this should raise an exception
raise TestFailed
, "expected a RuntimeError for print recursion"
if verbose
: print "Testing weak references..."
verify(str(msg
).find("weak reference") >= 0)
verify(0, "weakref.ref(no) should be illegal")
__slots__
= ['foo', '__weakref__']
if verbose
: print "Testing property..."
x
= property(getx
, setx
, delx
, doc
="I'm the x property.")
verify(not hasattr(a
, "x"))
verify(not hasattr(a
, "x"))
verify(not hasattr(a
, "_C__x"))
vereq(C
.x
.__get
__(a
), 100)
verify(not hasattr(a
, "x"))
verify(isinstance(raw
, property))
verify("__doc__" in attrs
)
vereq(raw
.__doc
__, "I'm the x property.")
verify(raw
.fget
is C
.__dict
__['getx'])
verify(raw
.fset
is C
.__dict
__['setx'])
verify(raw
.fdel
is C
.__dict
__['delx'])
for attr
in "__doc__", "fget", "fset", "fdel":
if str(msg
).find('readonly') < 0:
raise TestFailed("when setting readonly attr %r on a "
"property, got unexpected TypeError "
"msg %r" % (attr
, str(msg
)))
raise TestFailed("expected TypeError from trying to set "
"readonly %r attr on a property" % attr
)
__getitem__
= property(lambda s
: 1/0)
except ZeroDivisionError:
raise TestFailed
, "expected ZeroDivisionError from bad property"
if verbose
: print "Testing super..."
vereq(A().meth(1), "A(1)")
self
.__super
= super(B
, self
)
return "B(%r)" % a
+ self
.__super
.meth(a
)
vereq(B().meth(2), "B(2)A(2)")
return "C(%r)" % a
+ self
.__super
.meth(a
)
vereq(C().meth(3), "C(3)A(3)")
return "D(%r)" % a
+ super(D
, self
).meth(a
)
vereq(D().meth(4), "D(4)C(4)B(4)A(4)")
# Test for subclassing super
def __init__(self
, *args
):
return super(mysuper
, self
).__init
__(*args
)
return "E(%r)" % a
+ mysuper(E
, self
).meth(a
)
vereq(E().meth(5), "E(5)D(5)C(5)B(5)A(5)")
s
= self
.__super
# == mysuper(F, self)
return "F(%r)[%s]" % (a
, s
.__class
__.__name
__) + s
.meth(a
)
vereq(F().meth(6), "F(6)[mysuper]E(6)D(6)C(6)B(6)A(6)")
# Make sure certain errors are raised
raise TestFailed
, "shouldn't allow super(D, 42)"
raise TestFailed
, "shouldn't allow super(D, C())"
raise TestFailed
, "shouldn't allow super(D).__get__(12)"
raise TestFailed
, "shouldn't allow super(D).__get__(C())"
# Make sure data descriptors can be overridden and accessed via super
# (new feature in Python 2.3)
def getx(self
): return 42
def getx(self
): return "hello"
vereq(super(DDsub
, dd
).x
, 42)
# Ensure that super() lookup of descriptor from classmethod
aProp
= property(lambda self
: "foo")
return super(Sub
,klass
).aProp
veris(Sub
.test(), Base
.aProp
)
if verbose
: print "Testing inheritance from basic types..."
def __add__(self
, other
):
return hexint(int.__add
__(self
, other
))
# (Note that overriding __radd__ doesn't work,
# because the int type gets first dibs.)
vereq(repr(hexint(7) + 9), "0x10")
vereq(repr(hexint(1000) + 7), "0x3ef")
verify(int(a
).__class
__ is int)
vereq(hash(a
), hash(12345))
verify((+a
).__class
__ is int)
verify((a
>> 0).__class
__ is int)
verify((a
<< 0).__class
__ is int)
verify((hexint(0) << 12).__class
__ is int)
verify((hexint(0) >> 12).__class
__ is int)
def __add__(self
, other
):
return self
.__class
__(super(octlong
, self
).__add
__(other
))
vereq(str(octlong(3) + 5), "010")
# (Note that overriding __radd__ here only seems to work
# because the example uses a short int left argument.)
vereq(str(5 + octlong(3000)), "05675")
vereq(hash(a
), hash(12345L))
verify(long(a
).__class
__ is long)
verify((+a
).__class
__ is long)
verify((-a
).__class
__ is long)
verify((-octlong(0)).__class
__ is long)
verify((a
>> 0).__class
__ is long)
verify((a
<< 0).__class
__ is long)
verify((a
- 0).__class
__ is long)
verify((a
* 1).__class
__ is long)
verify((a
** 1).__class
__ is long)
verify((a
// 1).__class
__ is long)
verify((1 * a
).__class
__ is long)
verify((a |
0).__class
__ is long)
verify((a ^
0).__class
__ is long)
verify((a
& -1L).__class
__ is long)
verify((octlong(0) << 12).__class
__ is long)
verify((octlong(0) >> 12).__class
__ is long)
verify(abs(octlong(0)).__class
__ is long)
# Because octlong overrides __add__, we can't check the absence of +0
# optimizations using octlong.
verify((a
+ 0).__class
__ is long)
verify((0 + a
).__class
__ is long)
# Check that negative clones don't segfault
vereq(long(a
), -1) # verify PyNumber_Long() copies the sign bit
def __init__(self
, value
=0.0, prec
=12):
return "%.*g" % (self
.prec
, self
)
vereq(repr(precfloat(1.1)), "1.1")
verify(float(a
).__class
__ is float)
vereq(hash(a
), hash(12345.0))
verify((+a
).__class
__ is float)
class madcomplex(complex):
return "%.17gj%+.17g" % (self
.imag
, self
.real
)
veris(base
.__class
__, complex)
veris(complex(a
).__class
__, complex)
a
= madcomplex(a
) # just trying another form of the constructor
veris(complex(a
).__class
__, complex)
vereq(hash(a
), hash(base
))
veris((+a
).__class
__, complex)
veris((a
+ 0).__class
__, complex)
veris((a
- 0).__class
__, complex)
veris((a
* 1).__class
__, complex)
veris((a
/ 1).__class
__, complex)
if self
._rev
is not None:
self
._rev
= self
.__class
__(L
)
a
= madtuple((1,2,3,4,5,6,7,8,9,0))
vereq(a
, (1,2,3,4,5,6,7,8,9,0))
vereq(a
.rev(), madtuple((0,9,8,7,6,5,4,3,2,1)))
vereq(a
.rev().rev(), madtuple((1,2,3,4,5,6,7,8,9,0)))
a
= madtuple((1,2,3,4,5))
vereq(tuple(a
), (1,2,3,4,5))
verify(tuple(a
).__class
__ is tuple)
vereq(hash(a
), hash((1,2,3,4,5)))
verify(a
[:].__class
__ is tuple)
verify((a
* 1).__class
__ is tuple)
verify((a
* 0).__class
__ is tuple)
verify((a
+ ()).__class
__ is tuple)
verify(tuple(a
).__class
__ is tuple)
verify((a
+ a
).__class
__ is tuple)
verify((a
* 0).__class
__ is tuple)
verify((a
* 1).__class
__ is tuple)
verify((a
* 2).__class
__ is tuple)
verify(a
[:].__class
__ is tuple)
if self
._rev
is not None:
self
._rev
= self
.__class
__("".join(L
))
s
= madstring("abcdefghijklmnopqrstuvwxyz")
vereq(s
, "abcdefghijklmnopqrstuvwxyz")
vereq(s
.rev(), madstring("zyxwvutsrqponmlkjihgfedcba"))
vereq(s
.rev().rev(), madstring("abcdefghijklmnopqrstuvwxyz"))
s
= madstring("".join(map(chr, range(i
))))
verify(str(s
).__class
__ is str)
verify(str(s
).__class
__ is str)
vereq(hash(s
), hash(base
))
verify((s
+ "").__class
__ is str)
verify(("" + s
).__class
__ is str)
verify((s
* 0).__class
__ is str)
verify((s
* 1).__class
__ is str)
verify((s
* 2).__class
__ is str)
vereq(s
* 2, base
+ base
)
verify(s
[:].__class
__ is str)
verify(s
[0:0].__class
__ is str)
verify(s
.strip().__class
__ is str)
verify(s
.lstrip().__class
__ is str)
verify(s
.rstrip().__class
__ is str)
identitytab
= ''.join([chr(i
) for i
in range(256)])
verify(s
.translate(identitytab
).__class
__ is str)
vereq(s
.translate(identitytab
), base
)
verify(s
.translate(identitytab
, "x").__class
__ is str)
vereq(s
.translate(identitytab
, "x"), base
)
vereq(s
.translate(identitytab
, "\x00"), "")
verify(s
.replace("x", "x").__class
__ is str)
vereq(s
.replace("x", "x"), base
)
verify(s
.ljust(len(s
)).__class
__ is str)
vereq(s
.ljust(len(s
)), base
)
verify(s
.rjust(len(s
)).__class
__ is str)
vereq(s
.rjust(len(s
)), base
)
verify(s
.center(len(s
)).__class
__ is str)
vereq(s
.center(len(s
)), base
)
verify(s
.lower().__class
__ is str)
class madunicode(unicode):
if self
._rev
is not None:
self
._rev
= self
.__class
__(u
"".join(L
))
vereq(u
.rev(), madunicode(u
"FEDCBA"))
vereq(u
.rev().rev(), madunicode(u
"ABCDEF"))
verify(unicode(u
).__class
__ is unicode)
vereq(hash(u
), hash(base
))
verify(u
.strip().__class
__ is unicode)
verify(u
.lstrip().__class
__ is unicode)
verify(u
.rstrip().__class
__ is unicode)
verify(u
.replace(u
"x", u
"x").__class
__ is unicode)
vereq(u
.replace(u
"x", u
"x"), base
)
verify(u
.replace(u
"xy", u
"xy").__class
__ is unicode)
vereq(u
.replace(u
"xy", u
"xy"), base
)
verify(u
.center(len(u
)).__class
__ is unicode)
vereq(u
.center(len(u
)), base
)
verify(u
.ljust(len(u
)).__class
__ is unicode)
vereq(u
.ljust(len(u
)), base
)
verify(u
.rjust(len(u
)).__class
__ is unicode)
vereq(u
.rjust(len(u
)), base
)
verify(u
.lower().__class
__ is unicode)
verify(u
.upper().__class
__ is unicode)
verify(u
.capitalize().__class
__ is unicode)
vereq(u
.capitalize(), base
)
verify(u
.title().__class
__ is unicode)
verify((u
+ u
"").__class
__ is unicode)
verify((u
"" + u
).__class
__ is unicode)
verify((u
* 0).__class
__ is unicode)
verify((u
* 1).__class
__ is unicode)
verify((u
* 2).__class
__ is unicode)
vereq(u
* 2, base
+ base
)
verify(u
[:].__class
__ is unicode)
verify(u
[0:0].__class
__ is unicode)
vereq(a
, range(5) + ["hello"])
vereq(list(a
), range(10))
class CountedInput(file):
"""Counts lines read by self.readline().
self.lineno is the 0-based ordinal of the last line read, up to
a maximum of one greater than the number of lines in the file.
self.ateof is true if and only if the final "" line has been read,
at which point self.lineno stops incrementing, and further calls
to readline() continue to return "".
# s = super(CountedInput, self).readline()
f
= file(name
=TESTFN
, mode
='w')
lines
= ['a\n', 'b\n', 'c\n']
for (i
, expected
) in zip(range(1, 5) + [4], lines
+ 2 * [""]):
vereq(f
.ateof
, (i
> len(lines
)))
print "Testing keyword args to basic type constructors ..."
vereq(complex(imag
=42, real
=666), complex(666, 42))
vereq(str(object=500), '500')
vereq(unicode(string
='abc', errors
='strict'), u
'abc')
vereq(tuple(sequence
=range(3)), (0, 1, 2))
vereq(list(sequence
=(0, 1, 2)), range(3))
# note: as of Python 2.3, dict() no longer has an "items" keyword arg
for constructor
in (int, float, long, complex, str, unicode,
constructor(bogus_keyword_arg
=1)
raise TestFailed("expected TypeError from bogus keyword "
"argument to %r" % constructor
)
# XXX This test is disabled because rexec is not deemed safe
print "Testing interaction with restricted execution ..."
code1
= """f = open(%r, 'w')""" % TESTFN
code2
= """f = file(%r, 'w')""" % TESTFN
t = type(f) # a sneaky way to get the file() constructor
f = t(%r, 'w') # rexec can't catch this by itself
f
= open(TESTFN
, 'w') # Create the file so code3 can find it.
for code
in code1
, code2
, code3
:
if str(msg
).find("restricted") >= 0:
outcome
= "got an exception, but not an expected one"
outcome
= "expected a restricted-execution exception"
raise TestFailed("%s, in %r" % (outcome
, code
))
def str_subclass_as_dict_key():
print "Testing a str subclass used as dict key .."
"""Sublcass of str that computes __eq__ case-insensitively.
Also computes a hash code of the string in canonical form.
def __init__(self
, value
):
self
.canonical
= value
.lower()
self
.hashcode
= hash(self
.canonical
)
if not isinstance(other
, cistr
):
return self
.canonical
== other
.canonical
vereq(cistr('ABC'), 'abc')
vereq('aBc', cistr('ABC'))
vereq(str(cistr('ABC')), 'ABC')
d
= {cistr('one'): 1, cistr('two'): 2, cistr('tHree'): 3}
vereq(d
[cistr('one')], 1)
vereq(d
[cistr('tWo')], 2)
vereq(d
[cistr('THrEE')], 3)
verify(cistr('ONe') in d
)
vereq(d
.get(cistr('thrEE')), 3)
def classic_comparisons():
if verbose
: print "Testing classic comparisons..."
for base
in (classic
, int, object):
if verbose
: print " (base = %s)" % base
def __init__(self
, value
):
def __cmp__(self
, other
):
return cmp(self
.value
, other
.value
)
if isinstance(other
, int) or isinstance(other
, long):
return cmp(self
.value
, other
)
c
= {1: c1
, 2: c2
, 3: c3
}
verify(cmp(c
[x
], c
[y
]) == cmp(x
, y
), "x=%d, y=%d" % (x
, y
))
for op
in "<", "<=", "==", "!=", ">", ">=":
verify(eval("c[x] %s c[y]" % op
) == eval("x %s y" % op
),
verify(cmp(c
[x
], y
) == cmp(x
, y
), "x=%d, y=%d" % (x
, y
))
verify(cmp(x
, c
[y
]) == cmp(x
, y
), "x=%d, y=%d" % (x
, y
))
print "Testing rich comparisons..."
return abs(self
- other
) <= 1e-6
for base
in (classic
, int, object, list):
if verbose
: print " (base = %s)" % base
def __init__(self
, value
):
def __cmp__(self
, other
):
raise TestFailed
, "shouldn't call __cmp__"
return self
.value
== other
.value
if isinstance(other
, int) or isinstance(other
, long):
return self
.value
== other
return self
.value
!= other
.value
if isinstance(other
, int) or isinstance(other
, long):
return self
.value
!= other
return self
.value
< other
.value
if isinstance(other
, int) or isinstance(other
, long):
return self
.value
< other
return self
.value
<= other
.value
if isinstance(other
, int) or isinstance(other
, long):
return self
.value
<= other
return self
.value
> other
.value
if isinstance(other
, int) or isinstance(other
, long):
return self
.value
> other
return self
.value
>= other
.value
if isinstance(other
, int) or isinstance(other
, long):
return self
.value
>= other
c
= {1: c1
, 2: c2
, 3: c3
}
for op
in "<", "<=", "==", "!=", ">", ">=":
verify(eval("c[x] %s c[y]" % op
) == eval("x %s y" % op
),
verify(eval("c[x] %s y" % op
) == eval("x %s y" % op
),
verify(eval("x %s c[y]" % op
) == eval("x %s y" % op
),
if verbose
: print "Testing coercions..."
if verbose
: print "Testing descriptor doc strings..."
vereq(descr
.__doc
__, what
)
check(file.closed
, "True if the file is closed") # getset descriptor
check(file.name
, "file name") # member descriptor
if verbose
: print "Testing __class__ assignment..."
verify(x
.__class
__ is cls2
)
verify(x
.__class
__ is cls
)
raise TestFailed
, "shouldn't allow %r.__class__ = %r" % (x
, C
)
raise TestFailed
, "shouldn't allow del %r.__class__" % x
class Int(int): __slots__
= []
if verbose
: print "Testing __dict__ assignment..."
raise TestFailed
, "shouldn't allow %r.__dict__ = %r" % (x
, dict)
del a
.__dict
__ # Deleting __dict__ is allowed
# Classes don't allow __dict__ assignment
print "Testing pickling and copying new-style classes and objects..."
def __init__(self
, a
, b
):
super(C
, self
).__init
__()
return "C(%r, %r)" % (self
.a
, self
.b
)
return super(C1
, cls
).__new
__(cls
)
def __getnewargs__(self
):
def __init__(self
, a
, b
):
return "C1(%r, %r)<%r>" % (self
.a
, self
.b
, list(self
))
def __new__(cls
, a
, b
, val
=0):
return super(C2
, cls
).__new
__(cls
, val
)
def __getnewargs__(self
):
return (self
.a
, self
.b
, int(self
))
def __init__(self
, a
, b
, val
=0):
return "C2(%r, %r)<%r>" % (self
.a
, self
.b
, int(self
))
def __setstate__(self
, foo
):
class C4classic
: # classic
class C4(C4classic
, object): # mixed inheritance
for p
in pickle
, cPickle
:
print p
.__name
__, ["text", "binary"][bin
]
a
= C1(1, 2); a
.append(42); a
.append(24)
b
= C2("hello", "world", 42)
vereq(x
.__class
__, a
.__class
__)
vereq(sorteditems(x
.__dict
__), sorteditems(a
.__dict
__))
vereq(y
.__class
__, b
.__class
__)
vereq(sorteditems(y
.__dict
__), sorteditems(b
.__dict
__))
# Test for __getstate__ and __setstate__ on new style class
veris(u
.__class
__, v
.__class
__)
# Test for picklability of hybrid class
veris(u
.__class
__, v
.__class
__)
# Testing copy.deepcopy()
cls2
= copy
.deepcopy(cls
)
a
= C1(1, 2); a
.append(42); a
.append(24)
b
= C2("hello", "world", 42)
x
, y
= copy
.deepcopy((a
, b
))
vereq(x
.__class
__, a
.__class
__)
vereq(sorteditems(x
.__dict
__), sorteditems(a
.__dict
__))
vereq(y
.__class
__, b
.__class
__)
vereq(sorteditems(y
.__dict
__), sorteditems(b
.__dict
__))
if verbose
: print "Testing pickling of classes with __slots__ ..."
# Pickling of classes with __slots__ but without __getstate__ should fail
raise TestFailed
, "should fail: pickle C instance - %s" % base
raise TestFailed
, "should fail: cPickle C instance - %s" % base
raise TestFailed
, "should fail: pickle D instance - %s" % base
raise TestFailed
, "should fail: cPickle D instance - %s" % base
# Give C a nice generic __getstate__ and __setstate__
for cls
in self
.__class
__.__mro
__:
for sn
in cls
.__dict
__.get('__slots__', ()):
d
[sn
] = getattr(self
, sn
)
def __setstate__(self
, d
):
y
= pickle
.loads(pickle
.dumps(x
))
vereq(hasattr(y
, 'a'), 0)
y
= cPickle
.loads(cPickle
.dumps(x
))
vereq(hasattr(y
, 'a'), 0)
y
= pickle
.loads(pickle
.dumps(x
))
y
= cPickle
.loads(cPickle
.dumps(x
))
y
= pickle
.loads(pickle
.dumps(x
))
y
= cPickle
.loads(cPickle
.dumps(x
))
# A subclass that adds a slot should also work
y
= pickle
.loads(pickle
.dumps(x
))
y
= cPickle
.loads(cPickle
.dumps(x
))
if verbose
: print "Testing copy.copy() and copy.deepcopy()..."
vereq(b
.__dict
__, a
.__dict
__)
vereq(d
.__dict
__, a
.__dict
__)
if verbose
: print "Testing overrides of binary operations..."
return "I(%r)" % int(self
)
def __add__(self
, other
):
return I(int(self
) + int(other
))
def __pow__(self
, other
, mod
=None):
return I(pow(int(self
), int(other
)))
return I(pow(int(self
), int(other
), int(mod
)))
def __rpow__(self
, other
, mod
=None):
return I(pow(int(other
), int(self
), mod
))
return I(pow(int(other
), int(self
), int(mod
)))
vereq(repr(I(1) + I(2)), "I(3)")
vereq(repr(I(1) + 2), "I(3)")
vereq(repr(1 + I(2)), "I(3)")
vereq(repr(I(2) ** I(3)), "I(8)")
vereq(repr(2 ** I(3)), "I(8)")
vereq(repr(I(2) ** 3), "I(8)")
vereq(repr(pow(I(2), I(3), I(5))), "I(3)")
return self
.lower() == other
.lower()
def subclasspropagation():
if verbose
: print "Testing propagation of slot functions to subclasses..."
A
.__hash
__ = lambda self
: 42
C
.__hash
__ = lambda self
: 314
B
.__hash
__ = lambda self
: 144
D
.__hash
__ = lambda self
: 100
def __getattribute__(self
, name
):
return object.__getattribute
__(self
, name
)
A
.__getattribute
__ = __getattribute__
def __getattr__(self
, name
):
if name
in ("spam", "foo", "bar"):
raise AttributeError, name
B
.__getattr
__ = __getattr__
raise TestFailed
, "d.foo should be undefined now"
# Test a nasty bug in recurse_down_subclasses()
A
.__setitem
__ = lambda *a
: None # crash
# SF bug [#470040] ParseTuple t# vs subclasses.
print "Testing that buffer interface is inherited ..."
# b2a_hex uses the buffer interface to get its argument's value, via
# PyArg_ParseTuple 't#' code.
vereq(binascii
.b2a_hex(m
), binascii
.b2a_hex(base
))
# It's not clear that unicode will continue to support the character
# buffer interface, and this test will fail if that's taken away.
vereq(binascii
.b2a_hex(m
), binascii
.b2a_hex(base
))
raise TestFailed('subclass of int should not have a buffer interface')
def str_of_str_subclass():
print "Testing __str__ defined in subclass of str ..."
return binascii
.b2a_hex(self
)
vereq(type(o
), octetstring
)
vereq(type(repr(o
)), str)
vereq(o
.__repr
__(), 'A repr')
capture
= cStringIO
.StringIO()
# Calling str() or not exercises different internal paths.
vereq(capture
.getvalue(), '41\n41\n')
if verbose
: print "Testing keyword arguments to __init__, __call__..."
vereq(f
.__call
__(a
=42), 42)
list.__init
__(a
, sequence
=[0, 1, 2])
if verbose
: print "Testing __del__ hook..."
else: raise TestFailed
, "invalid del() didn't raise TypeError"
if verbose
: print "Testing hash of mutable subclasses..."
raise TestFailed
, "hash() of dict subclass should fail"
raise TestFailed
, "hash() of list subclass should fail"
else: raise TestFailed
, "'' + 5 doesn't raise TypeError"
else: raise TestFailed
, "''.split('') doesn't raise ValueError"
else: raise TestFailed
, "''.join([0]) doesn't raise TypeError"
else: raise TestFailed
, "''.rindex('5') doesn't raise ValueError"
else: raise TestFailed
, "'%(n)s' % None doesn't raise TypeError"
else: raise TestFailed
, "'%(n' % {} '' doesn't raise ValueError"
else: raise TestFailed
, "'%*s' % ('abc') doesn't raise TypeError"
try: '%*.*s' % ('abc', 5)
else: raise TestFailed
, "'%*.*s' % ('abc', 5) doesn't raise TypeError"
else: raise TestFailed
, "'%s' % (1, 2) doesn't raise TypeError"
else: raise TestFailed
, "'%' % None doesn't raise ValueError"
vereq('534253'.isdigit(), 1)
vereq('534253x'.isdigit(), 0)
if verbose
: print "Testing deepcopy of recursive objects..."
z
= deepcopy(a
) # This blew up before
if verbose
: print "Testing uninitialized module objects..."
from types
import ModuleType
as M
vereq(hasattr(m
, "__name__"), 0)
vereq(hasattr(m
, "__file__"), 0)
vereq(hasattr(m
, "foo"), 0)
vereq(m
.__dict
__, {"foo": 1})
if verbose
: print "Testing dict-proxy iterkeys..."
keys
= [ key
for key
in C
.__dict
__.iterkeys() ]
vereq(keys
, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth'])
def dictproxyitervalues():
if verbose
: print "Testing dict-proxy itervalues..."
values
= [ values
for values
in C
.__dict
__.itervalues() ]
def dictproxyiteritems():
if verbose
: print "Testing dict-proxy iteritems..."
keys
= [ key
for (key
, value
) in C
.__dict
__.iteritems() ]
vereq(keys
, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth'])
if verbose
: print "Testing __new__ returning something unexpected..."
if isinstance(arg
, str): return [1, 2, 3]
elif isinstance(arg
, int): return object.__new
__(D
)
else: return object.__new
__(cls
)
vereq(isinstance(d
, D
), True)
vereq(isinstance(d
, D
), True)
if verbose
: print "Testing for __imul__ problems..."
def __imul__(self
, other
):
if verbose
: print "Testing __doc__ descriptor..."
def __get__(self
, object, otype
):
object = object.__class
__.__name
__ + ' instance'
return 'object=%s; type=%s' % (object, otype
)
vereq(OldClass
.__doc
__, 'object=None; type=OldClass')
vereq(OldClass().__doc
__, 'object=OldClass instance; type=OldClass')
vereq(NewClass
.__doc
__, 'object=None; type=NewClass')
vereq(NewClass().__doc
__, 'object=NewClass instance; type=NewClass')
print "Testing string exceptions ..."
# Ensure builtin strings work OK as exceptions.
astring
= "An exception string."
raise TestFailed
, "builtin string not usable as exception"
# Ensure string subclass instances do not.
newstring
= MyStr("oops -- shouldn't work")
raise TestFailed
, "string subclass allowed as exception"
print "Testing that copy.*copy() correctly uses __setstate__..."
def __init__(self
, foo
=None):
def setfoo(self
, foo
=None):
def __setstate__(self
, lst
):
self
.__foo
= self
.foo
= lst
[0]
print "Testing cases with slices and overridden __getitem__ ..."
vereq("hello"[:4], "hell")
vereq("hello"[slice(4)], "hell")
vereq(str.__getitem
__("hello", slice(4)), "hell")
def __getitem__(self
, x
):
return str.__getitem
__(self
, x
)
vereq(S("hello")[:4], "hell")
vereq(S("hello")[slice(4)], "hell")
vereq(S("hello").__getitem
__(slice(4)), "hell")
vereq((1,2,3)[:2], (1,2))
vereq((1,2,3)[slice(2)], (1,2))
vereq(tuple.__getitem
__((1,2,3), slice(2)), (1,2))
def __getitem__(self
, x
):
return tuple.__getitem
__(self
, x
)
vereq(T((1,2,3))[:2], (1,2))
vereq(T((1,2,3))[slice(2)], (1,2))
vereq(T((1,2,3)).__getitem
__(slice(2)), (1,2))
vereq([1,2,3][:2], [1,2])
vereq([1,2,3][slice(2)], [1,2])
vereq(list.__getitem
__([1,2,3], slice(2)), [1,2])
def __getitem__(self
, x
):
return list.__getitem
__(self
, x
)
vereq(L([1,2,3])[:2], [1,2])
vereq(L([1,2,3])[slice(2)], [1,2])
vereq(L([1,2,3]).__getitem
__(slice(2)), [1,2])
# Now do lists and __setitem__
a
[slice(0, 2, 1)] = [3,1]
a
.__setitem
__(slice(1, 3), [2,1])
a
.__setitem
__(slice(0, 2, 1), [2,3])
def subtype_resurrection():
print "Testing resurrection of new-style instance..."
# The most interesting thing here is whether this blows up, due to flawed
# GC tracking logic in typeobject.c's call_finalizer() (a 2.2.1 bug).
# If that didn't blow up, it's also interesting to see whether clearing
# the last container slot works: that will attempt to delete c again,
# which will cause c to get appended back to the container again "during"
vereq(len(C
.container
), 1)
vereq(C
.container
[-1].attr
, 42)
# Make c mortal again, so that the test framework with -l doesn't report
# Deallocating deeply nested slotted trash caused stack overflows
print "Testing slot trash..."
def slotmultipleinheritance():
# SF bug 575229, multiple inheritance w/ slots dumps core
vereq(C
.__basicsize
__, B
.__basicsize
__)
verify(hasattr(C
, '__dict__'))
verify(hasattr(C
, '__weakref__'))
print "Testing correct invocation of __rmul__..."
def __mul__(self
, other
):
def __rmul__(self
, other
):
print "Testing correct invocation of __ipow__..."
def __ipow__(self
, other
):
print "Testing SF bug 551412 ..."
# This dumps core when SF bug 551412 isn't fixed --
# but only when test_descr.py is run separately.
# (That can't be helped -- as soon as PyType_Ready()
# is called for PyLong_Type, the bug is gone.)
def __pow__(self
, *args
):
print "Testing SF bug 570483..."
# Another segfault only when run early
# (before PyType_Ready(tuple) is called)
def test_mutable_bases():
print "Testing mutable bases..."
# stuff that should work:
def __getattribute__(self
, attr
):
return super(C2
, self
).__getattribute
__(attr
)
vereq(C2
.__subclasses__(), [D
])
raise TestFailed
, "shouldn't turn list subclass into dict subclass"
raise TestFailed
, "shouldn't be able to assign to list.__bases__"
raise TestFailed
, "shouldn't be able to delete .__bases__"
if str(msg
) == "a new-style class can't have only classic bases":
raise TestFailed
, "wrong error message for .__bases__ = ()"
raise TestFailed
, "shouldn't be able to set .__bases__ to ()"
# actually, we'll have crashed by here...
raise TestFailed
, "shouldn't be able to create inheritance cycles"
raise TestFailed
, "didn't detect repeated base classes"
raise TestFailed
, "shouldn't be able to create inheritance cycles"
# let's throw a classic class into the mix:
D
.__bases
__ = (C
, Classic
)
raise TestFailed
, "attribute should have vanished"
raise TestFailed
, "new-style class must have a new-style base"
def test_mutable_bases_with_failing_mro():
print "Testing mutable bases with failing mro..."
def __new__(self
, name
, bases
, ns
):
return super(WorkOnce
, self
).__new
__(WorkOnce
, name
, bases
, ns
)
raise RuntimeError, "bozo"
# this is here to make sure that .mro()s aren't called
# with an exception set (which was possible at one point).
# An error message will be printed in a debug build.
# What's a good way to test for this?
__metaclass__
= WorkAlways
# Immediate subclasses have their mro's adjusted in alphabetical
# order, so E's will get adjusted before adjusting F's fails. We
# check here that E's gets restored.
vereq(E
.__mro
__, E_mro_before
)
vereq(D
.__mro
__, D_mro_before
)
raise TestFailed
, "exception not propagated"
def test_mutable_bases_catch_mro_conflict():
print "Testing mutable bases catch mro conflict..."
raise TestFailed
, "didn't catch MRO conflict"
print "Testing mutable names..."
# C.__module__ could be 'test_descr' or '__main__'
vereq((C
.__module
__, C
.__name
__), (mod
, 'D'))
vereq((C
.__module
__, C
.__name
__), (mod
, 'D.E'))
print "Testing correct dispatch of subclass overloading __r<op>__..."
# This code tests various cases where right-dispatch of a subclass
# should be preferred over left-dispatch of a base class.
# Case 1: subclass of int; this tests code in abstract.c::binary_op1()
def __floordiv__(self
, other
):
def __rfloordiv__(self
, other
):
vereq(B(1) // 1, "B.__floordiv__")
vereq(1 // B(1), "B.__rfloordiv__")
# Case 2: subclass of object; this is just the baseline for case 3
def __floordiv__(self
, other
):
def __rfloordiv__(self
, other
):
vereq(C() // 1, "C.__floordiv__")
vereq(1 // C(), "C.__rfloordiv__")
# Case 3: subclass of new-style class; here it gets interesting
def __floordiv__(self
, other
):
def __rfloordiv__(self
, other
):
vereq(D() // C(), "D.__floordiv__")
vereq(C() // D(), "D.__rfloordiv__")
# Case 4: this didn't work right in 2.2.2 and 2.3a1
vereq(E
.__rfloordiv
__, C
.__rfloordiv
__)
vereq(E() // 1, "C.__floordiv__")
vereq(1 // E(), "C.__rfloordiv__")
vereq(E() // C(), "C.__floordiv__")
vereq(C() // E(), "C.__floordiv__") # This one would fail
def dict_type_with_metaclass():
print "Testing type of __dict__ when __metaclass__ set..."
# In 2.3a1, C.__dict__ was a real dict rather than a dict proxy
veris(type(C
.__dict
__), type(B
.__dict
__))
# Full coverage of descrobject.c::classmethod_get()
print "Testing __get__ method of METH_CLASS C methods..."
res
= {1: None, 2: None, 3: None}
vereq(dict.fromkeys(arg
), res
)
vereq({}.fromkeys(arg
), res
)
descr
= dict.__dict
__["fromkeys"]
# More baseline using the descriptor directly
vereq(descr
.__get
__(None, dict)(arg
), res
)
vereq(descr
.__get
__({})(arg
), res
)
# Now check various error cases
descr
.__get
__(None, None)
raise TestFailed
, "shouldn't have allowed descr.__get__(None, None)"
raise TestFailed
, "shouldn't have allowed descr.__get__(42)"
raise TestFailed
, "shouldn't have allowed descr.__get__(None, 42)"
raise TestFailed
, "shouldn't have allowed descr.__get__(None, int)"
print "Testing proxy isinstance() and isclass()..."
def __getattribute__(self
, name
):
if name
.startswith("_Proxy__"):
return object.__getattribute
__(self
, name
)
return getattr(self
.__obj
, name
)
# Test with a classic class
verify(isinstance(a
, C
)) # Baseline
verify(isinstance(pa
, C
)) # Test
# Test with a classic subclass
verify(isinstance(a
, C
)) # Baseline
verify(isinstance(pa
, C
)) # Test
# Test with a new-style class
verify(isinstance(a
, C
)) # Baseline
verify(isinstance(pa
, C
)) # Test
# Test with a new-style subclass
verify(isinstance(a
, C
)) # Baseline
verify(isinstance(pa
, C
)) # Test
print "Testing super() for a proxy object..."
def __getattribute__(self
, name
):
if name
.startswith("_Proxy__"):
return object.__getattribute
__(self
, name
)
return getattr(self
.__obj
, name
)
return super(C
, self
).f() + "->C.f"
vereq(C
.__dict
__["f"](p
), "B.f->C.f")
print "Testing prohibition of Carlo Verre's hack..."
object.__setattr
__(str, "foo", 42)
raise TestFailed
, "Carlo Verre __setattr__ suceeded!"
object.__delattr
__(str, "lower")
raise TestFailed
, "Carlo Verre __delattr__ succeeded!"
print "Testing weakref segfault..."
def __init__(self
, referrent
):
self
.ref
= weakref
.ref(referrent
)
# Fix SF #762455, segfault when sys.stdout is changed in getattr
print "Testing sys.stdout is changed in getattr..."
def __getattr__(self
, attr
):
sys
.stdout
= sys
.__stdout
__
raise RuntimeError("Premature access to sys.stdout.%s" % attr
)
sys
.stdout
= StdoutGuard()
def vicious_descriptor_nonsense():
# A potential segfault spotted by Thomas Wouters in mail to
# python-dev 2003-04-17, turned into an example & fixed by Michael
# Hudson just less than four months later...
print "Testing vicious_descriptor_nonsense..."
def __get__(self
, ob
, type=None):
# this makes a crash more likely:
vereq(hasattr(c
, 'attr'), False)
oldfilters
= warnings
.filters
[:]
warnings
.filterwarnings("error", category
=RuntimeWarning)
raise TestFailed
, "did not test __init__() for None return"
warnings
.filters
= oldfilters
weakref_segfault() # Must be first, somehow
str_subclass_as_dict_key()
slotmultipleinheritance()
test_mutable_bases_with_failing_mro()
test_mutable_bases_catch_mro_conflict()
dict_type_with_metaclass()
vicious_descriptor_nonsense()
if verbose
: print "All OK"
if __name__
== "__main__":