[Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.26,1.27

Guido van Rossum gvanrossum@users.sourceforge.net
Thu, 30 Aug 2001 13:52:42 -0700


Update of /cvsroot/python/python/dist/src/Lib/test
In directory usw-pr-cvs1:/tmp/cvs-serv10900

Modified Files:
	test_descr.py 
Log Message:
metaclass(): add some more examples of metaclasses, including one
using cooperative multiple inheritance.

inherits(): add a test for subclassing the unicode type.


Index: test_descr.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -d -r1.26 -r1.27
*** test_descr.py	2001/08/30 20:06:08	1.26
--- test_descr.py	2001/08/30 20:52:40	1.27
***************
*** 393,396 ****
--- 393,397 ----
      c = C()
      verify(c.__spam__ == 1)
+ 
      class _instance(object):
          pass
***************
*** 421,424 ****
--- 422,515 ----
      verify(c.spam() == 42)
  
+     # More metaclass examples
+ 
+     class autosuper(type):
+         # Automatically add __super to the class
+         # This trick only works for dynamic classes
+         # so we force __dynamic__ = 1
+         def __new__(metaclass, name, bases, dict):
+             # XXX Should check that name isn't already a base class name
+             dict["__dynamic__"] = 1
+             cls = super(autosuper, metaclass).__new__(metaclass,
+                                                       name, bases, dict)
+             while name[:1] == "_":
+                 name = name[1:]
+             while name[-1:] == "_":
+                 name = name[:-1]
+             if name:
+                 name = "_%s__super" % name
+             else:
+                 name = "__super"
+             setattr(cls, name, super(cls))
+             return cls
+     class A:
+         __metaclass__ = autosuper
+         def meth(self):
+             return "A"
+     class B(A):
+         def meth(self):
+             return "B" + self.__super.meth()
+     class C(A):
+         def meth(self):
+             return "C" + self.__super.meth()
+     class D(C, B):
+         def meth(self):
+             return "D" + self.__super.meth()
+     verify(D().meth() == "DCBA")
+     class E(B, C):
+         def meth(self):
+             return "E" + self.__super.meth()
+     verify(E().meth() == "EBCA")
+ 
+     class autogetset(type):
+         # Automatically create getset attributes when methods
+         # named _get_x and/or _set_x are found
+         def __new__(metaclass, name, bases, dict):
+             hits = {}
+             for key, val in dict.iteritems():
+                 if key.startswith("_get_"):
+                     key = key[5:]
+                     get, set = hits.get(key, (None, None))
+                     get = val
+                     hits[key] = get, set
+                 elif key.startswith("_set_"):
+                     key = key[5:]
+                     get, set = hits.get(key, (None, None))
+                     set = val
+                     hits[key] = get, set
+             for key, (get, set) in hits.iteritems():
+                 dict[key] = getset(get, set)
+             return super(autogetset, metaclass).__new__(metaclass,
+                                                         name, bases, dict)
+     class A:
+         __metaclass__ = autogetset
+         def _get_x(self):
+             return -self.__x
+         def _set_x(self, x):
+             self.__x = -x
+     a = A()
+     verify(not hasattr(a, "x"))
+     a.x = 12
+     verify(a.x == 12)
+     verify(a._A__x == -12)
+ 
+     class multimetaclass(autogetset, autosuper):
+         # Merge of multiple cooperating metaclasses
+         pass
+     class A:
+         __metaclass__ = multimetaclass
+         def _get_x(self):
+             return "A"
+     class B(A):
+         def _get_x(self):
+             return "B" + self.__super._get_x()
+     class C(A):
+         def _get_x(self):
+             return "C" + self.__super._get_x()
+     class D(C, B):
+         def _get_x(self):
+             return "D" + self.__super._get_x()
+     verify(D().x == "DCBA")
+ 
  def pymods():
      if verbose: print "Testing Python subclass of module..."
***************
*** 1193,1196 ****
--- 1284,1300 ----
          u = t.rev()
          verify(u == s)
+ 
+     class madunicode(unicode):
+         _rev = None
+         def rev(self):
+             if self._rev is not None:
+                 return self._rev
+             L = list(self)
+             L.reverse()
+             self._rev = self.__class__(u"".join(L))
+             return self._rev
+     u = madunicode("ABCDEF")
+     verify(u.rev() == madunicode(u"FEDCBA"))
+     verify(u.rev().rev() == madunicode(u"ABCDEF"))
  
  def all():