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

Tim Peters tim_one@users.sourceforge.net
Thu, 13 Sep 2001 17:25:35 -0700


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

Modified Files:
	test_descr.py 
Log Message:
Changed the dict implementation to take "string shortcuts" only when
keys are true strings -- no subclasses need apply.  This may be debatable.

The problem is that a str subclass may very well want to override __eq__
and/or __hash__ (see the new example of case-insensitive strings in
test_descr), but go-fast shortcuts for strings are ubiquitous in our dicts
(and subclass overrides aren't even looked for then).  Another go-fast
reason for the change is that PyCheck_StringExact() is a quicker test
than PyCheck_String(), and we make such a test on virtually every access
to every dict.

OTOH, a str subclass may also be perfectly happy using the base str eq
and hash, and this change slows them a lot.  But those cases are still
hypothetical, while Python's own reliance on true-string dicts is not.


Index: test_descr.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v
retrieving revision 1.55
retrieving revision 1.56
diff -C2 -d -r1.55 -r1.56
*** test_descr.py	2001/09/13 21:01:29	1.55
--- test_descr.py	2001/09/14 00:25:33	1.56
***************
*** 1534,1539 ****
      verify(str(s).__class__ is str)
      verify(hash(s) == hash(base))
!     verify({s: 1}[base] == 1)
!     verify({base: 1}[s] == 1)
      verify((s + "").__class__ is str)
      verify(s + "" == base)
--- 1534,1539 ----
      verify(str(s).__class__ is str)
      verify(hash(s) == hash(base))
!     #XXX verify({s: 1}[base] == 1)
!     #XXX verify({base: 1}[s] == 1)
      verify((s + "").__class__ is str)
      verify(s + "" == base)
***************
*** 1759,1762 ****
--- 1759,1795 ----
              pass
  
+ def str_subclass_as_dict_key():
+     if verbose:
+         print "Testing a str subclass used as dict key .."
+ 
+     class cistr(str):
+         """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)
+ 
+         def __eq__(self, other):
+             if not isinstance(other, cistr):
+                 other = cistr(other)
+             return self.canonical == other.canonical
+ 
+         def __hash__(self):
+             return self.hashcode
+ 
+     verify('aBc' == cistr('ABC') == 'abc')
+     verify(str(cistr('ABC')) == 'ABC')
+ 
+     d = {cistr('one'): 1, cistr('two'): 2, cistr('tHree'): 3}
+     verify(d[cistr('one')] == 1)
+     verify(d[cistr('tWo')] == 2)
+     verify(d[cistr('THrEE')] == 3)
+     verify(cistr('ONe') in d)
+     verify(d.get(cistr('thrEE')) == 3)
+ 
+ 
  def all():
      lists()
***************
*** 1795,1798 ****
--- 1828,1832 ----
      keywords()
      restricted()
+     str_subclass_as_dict_key()
  
  all()