Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 91ee798

Browse files
committed
metaclass(): add some more examples of metaclasses, including one
using cooperative multiple inheritance. inherits(): add a test for subclassing the unicode type.
1 parent d507dab commit 91ee798

1 file changed

Lines changed: 104 additions & 0 deletions

File tree

Lib/test/test_descr.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ class C:
392392
verify(C.__spam__ == 1)
393393
c = C()
394394
verify(c.__spam__ == 1)
395+
395396
class _instance(object):
396397
pass
397398
class M2(object):
@@ -420,6 +421,96 @@ def spam(self):
420421
c = C()
421422
verify(c.spam() == 42)
422423

424+
# More metaclass examples
425+
426+
class autosuper(type):
427+
# Automatically add __super to the class
428+
# This trick only works for dynamic classes
429+
# so we force __dynamic__ = 1
430+
def __new__(metaclass, name, bases, dict):
431+
# XXX Should check that name isn't already a base class name
432+
dict["__dynamic__"] = 1
433+
cls = super(autosuper, metaclass).__new__(metaclass,
434+
name, bases, dict)
435+
while name[:1] == "_":
436+
name = name[1:]
437+
while name[-1:] == "_":
438+
name = name[:-1]
439+
if name:
440+
name = "_%s__super" % name
441+
else:
442+
name = "__super"
443+
setattr(cls, name, super(cls))
444+
return cls
445+
class A:
446+
__metaclass__ = autosuper
447+
def meth(self):
448+
return "A"
449+
class B(A):
450+
def meth(self):
451+
return "B" + self.__super.meth()
452+
class C(A):
453+
def meth(self):
454+
return "C" + self.__super.meth()
455+
class D(C, B):
456+
def meth(self):
457+
return "D" + self.__super.meth()
458+
verify(D().meth() == "DCBA")
459+
class E(B, C):
460+
def meth(self):
461+
return "E" + self.__super.meth()
462+
verify(E().meth() == "EBCA")
463+
464+
class autogetset(type):
465+
# Automatically create getset attributes when methods
466+
# named _get_x and/or _set_x are found
467+
def __new__(metaclass, name, bases, dict):
468+
hits = {}
469+
for key, val in dict.iteritems():
470+
if key.startswith("_get_"):
471+
key = key[5:]
472+
get, set = hits.get(key, (None, None))
473+
get = val
474+
hits[key] = get, set
475+
elif key.startswith("_set_"):
476+
key = key[5:]
477+
get, set = hits.get(key, (None, None))
478+
set = val
479+
hits[key] = get, set
480+
for key, (get, set) in hits.iteritems():
481+
dict[key] = getset(get, set)
482+
return super(autogetset, metaclass).__new__(metaclass,
483+
name, bases, dict)
484+
class A:
485+
__metaclass__ = autogetset
486+
def _get_x(self):
487+
return -self.__x
488+
def _set_x(self, x):
489+
self.__x = -x
490+
a = A()
491+
verify(not hasattr(a, "x"))
492+
a.x = 12
493+
verify(a.x == 12)
494+
verify(a._A__x == -12)
495+
496+
class multimetaclass(autogetset, autosuper):
497+
# Merge of multiple cooperating metaclasses
498+
pass
499+
class A:
500+
__metaclass__ = multimetaclass
501+
def _get_x(self):
502+
return "A"
503+
class B(A):
504+
def _get_x(self):
505+
return "B" + self.__super._get_x()
506+
class C(A):
507+
def _get_x(self):
508+
return "C" + self.__super._get_x()
509+
class D(C, B):
510+
def _get_x(self):
511+
return "D" + self.__super._get_x()
512+
verify(D().x == "DCBA")
513+
423514
def pymods():
424515
if verbose: print "Testing Python subclass of module..."
425516
log = []
@@ -1193,6 +1284,19 @@ def rev(self):
11931284
u = t.rev()
11941285
verify(u == s)
11951286

1287+
class madunicode(unicode):
1288+
_rev = None
1289+
def rev(self):
1290+
if self._rev is not None:
1291+
return self._rev
1292+
L = list(self)
1293+
L.reverse()
1294+
self._rev = self.__class__(u"".join(L))
1295+
return self._rev
1296+
u = madunicode("ABCDEF")
1297+
verify(u.rev() == madunicode(u"FEDCBA"))
1298+
verify(u.rev().rev() == madunicode(u"ABCDEF"))
1299+
11961300
def all():
11971301
lists()
11981302
dicts()

0 commit comments

Comments
 (0)