Merge of descr-branch back into trunk.
diff --git a/Lib/pickle.py b/Lib/pickle.py
index f6cbea8..c92dac2 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -504,6 +504,7 @@
dispatch[ClassType] = save_global
dispatch[FunctionType] = save_global
dispatch[BuiltinFunctionType] = save_global
+ dispatch[TypeType] = save_global
def _keep_alive(x, memo):
diff --git a/Lib/repr.py b/Lib/repr.py
index c2d3ed5..f9cfcf6 100644
--- a/Lib/repr.py
+++ b/Lib/repr.py
@@ -62,7 +62,7 @@
s = s + ': ' + self.repr1(x[key], level-1)
if n > self.maxdict: s = s + ', ...'
return '{' + s + '}'
- def repr_string(self, x, level):
+ def repr_str(self, x, level):
s = `x[:self.maxstring]`
if len(s) > self.maxstring:
i = max(0, (self.maxstring-3)/2)
@@ -70,7 +70,7 @@
s = `x[:i] + x[len(x)-j:]`
s = s[:i] + '...' + s[len(s)-j:]
return s
- def repr_long_int(self, x, level):
+ def repr_long(self, x, level):
s = `x` # XXX Hope this isn't too slow...
if len(s) > self.maxlong:
i = max(0, (self.maxlong-3)/2)
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
new file mode 100644
index 0000000..92f79d5
--- /dev/null
+++ b/Lib/test/test_descr.py
@@ -0,0 +1,829 @@
+# Test descriptor-related enhancements
+
+from test_support import verify, verbose
+from copy import deepcopy
+
+def testunop(a, res, expr="len(a)", meth="__len__"):
+ if verbose: print "checking", expr
+ dict = {'a': a}
+ verify(eval(expr, dict) == res)
+ t = type(a)
+ m = getattr(t, meth)
+ verify(m == t.__dict__[meth])
+ verify(m(a) == res)
+ bm = getattr(a, meth)
+ verify(bm() == res)
+
+def testbinop(a, b, res, expr="a+b", meth="__add__"):
+ if verbose: print "checking", expr
+ dict = {'a': a, 'b': b}
+ verify(eval(expr, dict) == res)
+ t = type(a)
+ m = getattr(t, meth)
+ verify(m == t.__dict__[meth])
+ verify(m(a, b) == res)
+ bm = getattr(a, meth)
+ verify(bm(b) == res)
+
+def testternop(a, b, c, res, expr="a[b:c]", meth="__getslice__"):
+ if verbose: print "checking", expr
+ dict = {'a': a, 'b': b, 'c': c}
+ verify(eval(expr, dict) == res)
+ t = type(a)
+ m = getattr(t, meth)
+ verify(m == t.__dict__[meth])
+ verify(m(a, b, c) == res)
+ bm = getattr(a, meth)
+ verify(bm(b, c) == res)
+
+def testsetop(a, b, res, stmt="a+=b", meth="__iadd__"):
+ if verbose: print "checking", stmt
+ dict = {'a': deepcopy(a), 'b': b}
+ exec stmt in dict
+ verify(dict['a'] == res)
+ t = type(a)
+ m = getattr(t, meth)
+ verify(m == t.__dict__[meth])
+ dict['a'] = deepcopy(a)
+ m(dict['a'], b)
+ verify(dict['a'] == res)
+ dict['a'] = deepcopy(a)
+ bm = getattr(dict['a'], meth)
+ bm(b)
+ verify(dict['a'] == res)
+
+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}
+ exec stmt in dict
+ verify(dict['a'] == res)
+ t = type(a)
+ m = getattr(t, meth)
+ verify(m == t.__dict__[meth])
+ dict['a'] = deepcopy(a)
+ m(dict['a'], b, c)
+ verify(dict['a'] == res)
+ dict['a'] = deepcopy(a)
+ bm = getattr(dict['a'], meth)
+ bm(b, c)
+ verify(dict['a'] == res)
+
+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}
+ exec stmt in dict
+ verify(dict['a'] == res)
+ t = type(a)
+ m = getattr(t, meth)
+ verify(m == t.__dict__[meth])
+ dict['a'] = deepcopy(a)
+ m(dict['a'], b, c, d)
+ verify(dict['a'] == res)
+ dict['a'] = deepcopy(a)
+ bm = getattr(dict['a'], meth)
+ bm(b, c, d)
+ verify(dict['a'] == res)
+
+def lists():
+ 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__")
+
+def dicts():
+ 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__")
+ d = {1:2,3:4}
+ l1 = []
+ for i in d.keys(): l1.append(i)
+ l = []
+ for i in iter(d): l.append(i)
+ verify(l == l1)
+ l = []
+ for i in d.__iter__(): l.append(i)
+ verify(l == l1)
+ l = []
+ for i in dictionary.__iter__(d): l.append(i)
+ verify(l == l1)
+ d = {1:2, 3:4}
+ testunop(d, 2, "len(a)", "__len__")
+ verify(eval(repr(d), {}) == d)
+ verify(eval(d.__repr__(), {}) == d)
+ testset2op({1:2,3:4}, 2, 3, {1:2,2:3,3:4}, "a[b]=c", "__setitem__")
+
+binops = {
+ 'add': '+',
+ 'sub': '-',
+ 'mul': '*',
+ 'div': '/',
+ 'mod': '%',
+ 'divmod': 'divmod',
+ 'pow': '**',
+ 'lshift': '<<',
+ 'rshift': '>>',
+ 'and': '&',
+ 'xor': '^',
+ 'or': '|',
+ 'cmp': 'cmp',
+ 'lt': '<',
+ 'le': '<=',
+ 'eq': '==',
+ 'ne': '!=',
+ 'gt': '>',
+ 'ge': '>=',
+ }
+
+for name, expr in binops.items():
+ if expr.islower():
+ expr = expr + "(a, b)"
+ else:
+ expr = 'a %s b' % expr
+ binops[name] = expr
+
+unops = {
+ 'pos': '+',
+ 'neg': '-',
+ 'abs': 'abs',
+ 'invert': '~',
+ 'int': 'int',
+ 'long': 'long',
+ 'float': 'float',
+ 'oct': 'oct',
+ 'hex': 'hex',
+ }
+
+for name, expr in unops.items():
+ if expr.islower():
+ expr = expr + "(a)"
+ else:
+ expr = '%s a' % expr
+ unops[name] = expr
+
+def numops(a, b, skip=[]):
+ dict = {'a': a, 'b': b}
+ for name, expr in binops.items():
+ if name not in skip:
+ name = "__%s__" % name
+ if hasattr(a, name):
+ res = eval(expr, dict)
+ testbinop(a, b, res, expr, name)
+ for name, expr in unops.items():
+ name = "__%s__" % name
+ if hasattr(a, name):
+ res = eval(expr, dict)
+ testunop(a, res, expr, name)
+
+def ints():
+ if verbose: print "Testing int operations..."
+ numops(100, 3)
+
+def longs():
+ if verbose: print "Testing long operations..."
+ numops(100L, 3L)
+
+def floats():
+ if verbose: print "Testing float operations..."
+ numops(100.0, 3.0)
+
+def complexes():
+ if verbose: print "Testing complex operations..."
+ numops(100.0j, 3.0j, skip=['lt', 'le', 'gt', 'ge'])
+ class Number(complex):
+ __slots__ = ['prec']
+ def __init__(self, *args, **kwds):
+ self.prec = kwds.get('prec', 12)
+ def __repr__(self):
+ prec = self.prec
+ if self.imag == 0.0:
+ return "%.*g" % (prec, self.real)
+ if self.real == 0.0:
+ return "%.*gj" % (prec, self.imag)
+ return "(%.*g+%.*gj)" % (prec, self.real, prec, self.imag)
+ __str__ = __repr__
+ a = Number(3.14, prec=6)
+ verify(`a` == "3.14")
+ verify(a.prec == 6)
+
+def spamlists():
+ if verbose: print "Testing spamlist operations..."
+ import copy, xxsubtype as spam
+ def spamlist(l, memo=None):
+ import xxsubtype as spam
+ return spam.spamlist(l)
+ # This is an ugly hack:
+ 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]),
+ "a+=b", "__iadd__")
+ 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__")
+ # Test subclassing
+ class C(spam.spamlist):
+ def foo(self): return 1
+ a = C()
+ verify(a == [])
+ verify(a.foo() == 1)
+ a.append(100)
+ verify(a == [100])
+ verify(a.getstate() == 0)
+ a.setstate(42)
+ verify(a.getstate() == 42)
+
+def spamdicts():
+ if verbose: print "Testing spamdict operations..."
+ import copy, xxsubtype as spam
+ def spamdict(d, memo=None):
+ import xxsubtype as spam
+ sd = spam.spamdict()
+ for k, v in d.items(): sd[k] = v
+ return sd
+ # This is an ugly hack:
+ 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__")
+ d = spamdict({1:2,3:4})
+ l1 = []
+ for i in d.keys(): l1.append(i)
+ l = []
+ for i in iter(d): l.append(i)
+ verify(l == l1)
+ l = []
+ for i in d.__iter__(): l.append(i)
+ verify(l == l1)
+ l = []
+ for i in type(spamdict({})).__iter__(d): l.append(i)
+ verify(l == l1)
+ straightd = {1:2, 3:4}
+ 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}),
+ "a[b]=c", "__setitem__")
+ # Test subclassing
+ class C(spam.spamdict):
+ def foo(self): return 1
+ a = C()
+ verify(a.items() == [])
+ verify(a.foo() == 1)
+ a['foo'] = 'bar'
+ verify(a.items() == [('foo', 'bar')])
+ verify(a.getstate() == 0)
+ a.setstate(100)
+ verify(a.getstate() == 100)
+
+def pydicts():
+ if verbose: print "Testing Python subclass of dict..."
+ verify(issubclass(dictionary, dictionary))
+ verify(isinstance({}, dictionary))
+ d = dictionary()
+ verify(d == {})
+ verify(d.__class__ is dictionary)
+ verify(isinstance(d, dictionary))
+ class C(dictionary):
+ state = -1
+ def __init__(self, *a, **kw):
+ if a:
+ assert len(a) == 1
+ self.state = a[0]
+ if kw:
+ for k, v in kw.items(): self[v] = k
+ def __getitem__(self, key):
+ return self.get(key, 0)
+ def __setitem__(self, key, value):
+ assert isinstance(key, type(0))
+ dictionary.__setitem__(self, key, value)
+ def setstate(self, state):
+ self.state = state
+ def getstate(self):
+ return self.state
+ verify(issubclass(C, dictionary))
+ a1 = C(12)
+ verify(a1.state == 12)
+ a2 = C(foo=1, bar=2)
+ verify(a2[1] == 'foo' and a2[2] == 'bar')
+ a = C()
+ verify(a.state == -1)
+ verify(a.getstate() == -1)
+ a.setstate(0)
+ verify(a.state == 0)
+ verify(a.getstate() == 0)
+ a.setstate(10)
+ verify(a.state == 10)
+ verify(a.getstate() == 10)
+ verify(a[42] == 0)
+ a[42] = 24
+ verify(a[42] == 24)
+ if verbose: print "pydict stress test ..."
+ N = 50
+ for i in range(N):
+ a[i] = C()
+ for j in range(N):
+ a[i][j] = i*j
+ for i in range(N):
+ for j in range(N):
+ verify(a[i][j] == i*j)
+
+def pylists():
+ if verbose: print "Testing Python subclass of list..."
+ class C(list):
+ def __getitem__(self, i):
+ return list.__getitem__(self, i) + 100
+ def __getslice__(self, i, j):
+ return (i, j)
+ a = C()
+ a.extend([0,1,2])
+ verify(a[0] == 100)
+ verify(a[1] == 101)
+ verify(a[2] == 102)
+ verify(a[100:200] == (100,200))
+
+def metaclass():
+ if verbose: print "Testing __metaclass__..."
+ global C
+ class C:
+ __metaclass__ = type
+ def __init__(self):
+ self.__state = 0
+ def getstate(self):
+ return self.__state
+ def setstate(self, state):
+ self.__state = state
+ a = C()
+ verify(a.getstate() == 0)
+ a.setstate(10)
+ verify(a.getstate() == 10)
+ class D:
+ class __metaclass__(type):
+ def myself(cls): return cls
+ verify(D.myself() == D)
+
+import sys
+MT = type(sys)
+
+def pymods():
+ if verbose: print "Testing Python subclass of module..."
+ global log
+ log = []
+ class MM(MT):
+ def __init__(self):
+ MT.__init__(self)
+ def __getattr__(self, name):
+ log.append(("getattr", name))
+ return MT.__getattr__(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)
+ a = MM()
+ a.foo = 12
+ x = a.foo
+ del a.foo
+ verify(log == [('getattr', '__init__'),
+ ('getattr', '__setattr__'),
+ ("setattr", "foo", 12),
+ ("getattr", "foo"),
+ ('getattr', '__delattr__'),
+ ("delattr", "foo")], log)
+
+def multi():
+ if verbose: print "Testing multiple inheritance..."
+ global C
+ class C(object):
+ def __init__(self):
+ self.__state = 0
+ def getstate(self):
+ return self.__state
+ def setstate(self, state):
+ self.__state = state
+ a = C()
+ verify(a.getstate() == 0)
+ a.setstate(10)
+ verify(a.getstate() == 10)
+ class D(dictionary, C):
+ def __init__(self):
+ type({}).__init__(self)
+ C.__init__(self)
+ d = D()
+ verify(d.keys() == [])
+ d["hello"] = "world"
+ verify(d.items() == [("hello", "world")])
+ verify(d["hello"] == "world")
+ verify(d.getstate() == 0)
+ d.setstate(10)
+ verify(d.getstate() == 10)
+ verify(D.__mro__ == (D, dictionary, C, object))
+
+def diamond():
+ if verbose: print "Testing multiple inheritance special cases..."
+ class A(object):
+ def spam(self): return "A"
+ verify(A().spam() == "A")
+ class B(A):
+ def boo(self): return "B"
+ def spam(self): return "B"
+ verify(B().spam() == "B")
+ verify(B().boo() == "B")
+ class C(A):
+ def boo(self): return "C"
+ verify(C().spam() == "A")
+ verify(C().boo() == "C")
+ class D(B, C): pass
+ verify(D().spam() == "B")
+ verify(D().boo() == "B")
+ verify(D.__mro__ == (D, B, C, A, object))
+ class E(C, B): pass
+ verify(E().spam() == "B")
+ verify(E().boo() == "C")
+ verify(E.__mro__ == (E, C, B, A, object))
+ class F(D, E): pass
+ verify(F().spam() == "B")
+ verify(F().boo() == "B")
+ verify(F.__mro__ == (F, D, E, B, C, A, object))
+ class G(E, D): pass
+ verify(G().spam() == "B")
+ verify(G().boo() == "C")
+ verify(G.__mro__ == (G, E, D, C, B, A, object))
+
+def objects():
+ if verbose: print "Testing object class..."
+ a = object()
+ verify(a.__class__ == object == type(a))
+ b = object()
+ verify(a is not b)
+ verify(not hasattr(a, "foo"))
+ try:
+ a.foo = 12
+ except TypeError:
+ pass
+ else:
+ verify(0, "object() should not allow setting a foo attribute")
+ verify(not hasattr(object(), "__dict__"))
+
+ class Cdict(object):
+ pass
+ x = Cdict()
+ verify(x.__dict__ is None)
+ x.foo = 1
+ verify(x.foo == 1)
+ verify(x.__dict__ == {'foo': 1})
+
+def slots():
+ if verbose: print "Testing __slots__..."
+ class C0(object):
+ __slots__ = []
+ x = C0()
+ verify(not hasattr(x, "__dict__"))
+ verify(not hasattr(x, "foo"))
+
+ class C1(object):
+ __slots__ = ['a']
+ x = C1()
+ verify(not hasattr(x, "__dict__"))
+ verify(x.a == None)
+ x.a = 1
+ verify(x.a == 1)
+ del x.a
+ verify(x.a == None)
+
+ class C3(object):
+ __slots__ = ['a', 'b', 'c']
+ x = C3()
+ verify(not hasattr(x, "__dict__"))
+ verify(x.a is None)
+ verify(x.b is None)
+ verify(x.c is None)
+ x.a = 1
+ x.b = 2
+ x.c = 3
+ verify(x.a == 1)
+ verify(x.b == 2)
+ verify(x.c == 3)
+
+def dynamics():
+ if verbose: print "Testing __dynamic__..."
+ verify(object.__dynamic__ == 0)
+ verify(list.__dynamic__ == 0)
+ class S1:
+ __metaclass__ = type
+ verify(S1.__dynamic__ == 0)
+ class S(object):
+ pass
+ verify(C.__dynamic__ == 0)
+ class D(object):
+ __dynamic__ = 1
+ verify(D.__dynamic__ == 1)
+ class E(D, S):
+ pass
+ verify(E.__dynamic__ == 1)
+ class F(S, D):
+ pass
+ verify(F.__dynamic__ == 1)
+ try:
+ S.foo = 1
+ except (AttributeError, TypeError):
+ pass
+ else:
+ verify(0, "assignment to a static class attribute should be illegal")
+ D.foo = 1
+ verify(D.foo == 1)
+ # Test that dynamic attributes are inherited
+ verify(E.foo == 1)
+ verify(F.foo == 1)
+ class SS(D):
+ __dynamic__ = 0
+ verify(SS.__dynamic__ == 0)
+ verify(SS.foo == 1)
+ try:
+ SS.foo = 1
+ except (AttributeError, TypeError):
+ pass
+ else:
+ verify(0, "assignment to SS.foo should be illegal")
+
+def errors():
+ if verbose: print "Testing errors..."
+
+ try:
+ class C(list, dictionary):
+ pass
+ except TypeError:
+ pass
+ else:
+ verify(0, "inheritance from both list and dict should be illegal")
+
+ try:
+ class C(object, None):
+ pass
+ except TypeError:
+ pass
+ else:
+ verify(0, "inheritance from non-type should be illegal")
+ class Classic:
+ pass
+
+ try:
+ class C(object, Classic):
+ pass
+ except TypeError:
+ pass
+ else:
+ verify(0, "inheritance from object and Classic should be illegal")
+
+ try:
+ class C(int):
+ pass
+ except TypeError:
+ pass
+ else:
+ verify(0, "inheritance from int should be illegal")
+
+ try:
+ class C(object):
+ __slots__ = 1
+ except TypeError:
+ pass
+ else:
+ verify(0, "__slots__ = 1 should be illegal")
+
+ try:
+ class C(object):
+ __slots__ = [1]
+ except TypeError:
+ pass
+ else:
+ verify(0, "__slots__ = [1] should be illegal")
+
+def classmethods():
+ if verbose: print "Testing class methods..."
+ class C(object):
+ def foo(*a): return a
+ goo = classmethod(foo)
+ c = C()
+ verify(C.goo(1) == (C, 1))
+ verify(c.goo(1) == (C, 1))
+ verify(c.foo(1) == (c, 1))
+ class D(C):
+ pass
+ d = D()
+ verify(D.goo(1) == (D, 1))
+ verify(d.goo(1) == (D, 1))
+ verify(d.foo(1) == (d, 1))
+ verify(D.foo(d, 1) == (d, 1))
+
+def staticmethods():
+ if verbose: print "Testing static methods..."
+ class C(object):
+ def foo(*a): return a
+ goo = staticmethod(foo)
+ c = C()
+ verify(C.goo(1) == (1,))
+ verify(c.goo(1) == (1,))
+ verify(c.foo(1) == (c, 1,))
+ class D(C):
+ pass
+ d = D()
+ verify(D.goo(1) == (1,))
+ verify(d.goo(1) == (1,))
+ verify(d.foo(1) == (d, 1))
+ verify(D.foo(d, 1) == (d, 1))
+
+def classic():
+ if verbose: print "Testing classic classes..."
+ class C:
+ def foo(*a): return a
+ goo = classmethod(foo)
+ c = C()
+ verify(C.goo(1) == (C, 1))
+ verify(c.goo(1) == (C, 1))
+ verify(c.foo(1) == (c, 1))
+ class D(C):
+ pass
+ d = D()
+ verify(D.goo(1) == (D, 1))
+ verify(d.goo(1) == (D, 1))
+ verify(d.foo(1) == (d, 1))
+ verify(D.foo(d, 1) == (d, 1))
+
+def compattr():
+ if verbose: print "Testing computed attributes..."
+ class C(object):
+ class computed_attribute(object):
+ def __init__(self, get, set=None):
+ self.__get = get
+ self.__set = set
+ def __get__(self, obj, type=None):
+ return self.__get(obj)
+ def __set__(self, obj, value):
+ return self.__set(obj, value)
+ def __init__(self):
+ self.__x = 0
+ def __get_x(self):
+ x = self.__x
+ self.__x = x+1
+ return x
+ def __set_x(self, x):
+ self.__x = x
+ x = computed_attribute(__get_x, __set_x)
+ a = C()
+ verify(a.x == 0)
+ verify(a.x == 1)
+ a.x = 10
+ verify(a.x == 10)
+ verify(a.x == 11)
+
+def newslot():
+ if verbose: print "Testing __new__ slot override..."
+ class C(list):
+ def __new__(cls):
+ self = list.__new__(cls)
+ self.foo = 1
+ return self
+ def __init__(self):
+ self.foo = self.foo + 2
+ a = C()
+ verify(a.foo == 3)
+ verify(a.__class__ is C)
+ class D(C):
+ pass
+ b = D()
+ verify(b.foo == 3)
+ verify(b.__class__ is D)
+
+class PerverseMetaType(type):
+ def mro(cls):
+ L = type.mro(cls)
+ L.reverse()
+ return L
+
+def altmro():
+ if verbose: print "Testing mro() and overriding it..."
+ class A(object):
+ def f(self): return "A"
+ class B(A):
+ pass
+ class C(A):
+ def f(self): return "C"
+ class D(B, C):
+ pass
+ verify(D.mro() == [D, B, C, A, object] == list(D.__mro__))
+ verify(D().f() == "C")
+ class X(A,B,C,D):
+ __metaclass__ = PerverseMetaType
+ verify(X.__mro__ == (object, A, C, B, D, X))
+ verify(X().f() == "A")
+
+def overloading():
+ if verbose: print "testing operator overloading..."
+
+ class B(object):
+ "Intermediate class because object doesn't have a __setattr__"
+
+ class C(B):
+
+ def __getattr__(self, name):
+ if name == "foo":
+ return ("getattr", name)
+ else:
+ return B.__getattr__(self, name)
+ def __setattr__(self, name, value):
+ if name == "foo":
+ self.setattr = (name, value)
+ else:
+ return B.__setattr__(self, name, value)
+ def __delattr__(self, name):
+ if name == "foo":
+ self.delattr = name
+ else:
+ return B.__delattr__(self, name)
+
+ def __getitem__(self, key):
+ return ("getitem", key)
+ def __setitem__(self, key, value):
+ self.setitem = (key, value)
+ def __delitem__(self, key):
+ self.delitem = 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):
+ self.delslice = (i, j)
+
+ a = C()
+ verify(a.foo == ("getattr", "foo"))
+ a.foo = 12
+ verify(a.setattr == ("foo", 12))
+ del a.foo
+ verify(a.delattr == "foo")
+
+ verify(a[12] == ("getitem", 12))
+ a[12] = 21
+ verify(a.setitem == (12, 21))
+ del a[12]
+ verify(a.delitem == 12)
+
+ verify(a[0:10] == ("getslice", 0, 10))
+ a[0:10] = "foo"
+ verify(a.setslice == (0, 10, "foo"))
+ del a[0:10]
+ verify(a.delslice == (0, 10))
+
+def all():
+ lists()
+ dicts()
+ ints()
+ longs()
+ floats()
+ complexes()
+ spamlists()
+ spamdicts()
+ pydicts()
+ pylists()
+ metaclass()
+ pymods()
+ multi()
+ diamond()
+ objects()
+ slots()
+ dynamics()
+ errors()
+ classmethods()
+ staticmethods()
+ classic()
+ compattr()
+ newslot()
+ altmro()
+ overloading()
+
+all()
+
+if verbose: print "All OK"
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 2a174c3..72a70ec 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -380,10 +380,16 @@
>>> i = g()
>>> type(i)
<type 'generator'>
+
+XXX dir(object) *generally* doesn't return useful stuff in descr-branch.
>>> dir(i)
+[]
+
+Was hoping to see this instead:
['gi_frame', 'gi_running', 'next']
+
>>> print i.next.__doc__
-next() -- get the next value, or raise StopIteration
+x.next() -> the next value, or raise StopIteration
>>> iter(i) is i
1
>>> import types
@@ -399,7 +405,7 @@
>>> i.gi_running = 42
Traceback (most recent call last):
...
-TypeError: object has read-only attributes
+TypeError: 'generator' object has only read-only attributes (assign to .gi_running)
>>> def g():
... yield me.gi_running
>>> me = g()
diff --git a/Lib/types.py b/Lib/types.py
index 95600a3..d60ee56d 100644
--- a/Lib/types.py
+++ b/Lib/types.py
@@ -7,7 +7,8 @@
import sys
NoneType = type(None)
-TypeType = type(NoneType)
+TypeType = type
+ObjectType = object
IntType = type(0)
LongType = type(0L)
@@ -22,8 +23,8 @@
BufferType = type(buffer(''))
TupleType = type(())
-ListType = type([])
-DictType = DictionaryType = type({})
+ListType = list
+DictType = DictionaryType = dictionary
def _f(): pass
FunctionType = type(_f)
@@ -71,4 +72,9 @@
SliceType = type(slice(0))
EllipsisType = type(Ellipsis)
+DictIterType = type(iter({}))
+SequenceIterType = type(iter([]))
+FunctionIterType = type(iter(lambda: 0, 0))
+DictProxyType = type(TypeType.__dict__)
+
del sys, _f, _C, _x # Not for export