[Jython-checkins] jython: #2088 Fix defaultdict so that derived classes __missing__ methods are not

jim.baker jython-checkins at python.org
Thu May 22 22:02:41 CEST 2014


http://hg.python.org/jython/rev/9c9fe8e61cf0
changeset:   7265:9c9fe8e61cf0
parent:      7256:8ceb0723b372
user:        Indra Talip <indra.talip at gmail.com>
date:        Sun May 18 21:11:38 2014 +1000
summary:
  #2088 Fix defaultdict so that derived classes __missing__ methods are not ignored.

files:
  Lib/test/test_defaultdict_jy.py                        |  32 +++++++++-
  src/org/python/modules/_collections/PyDefaultDict.java |   8 ++
  2 files changed, 39 insertions(+), 1 deletions(-)


diff --git a/Lib/test/test_defaultdict_jy.py b/Lib/test/test_defaultdict_jy.py
--- a/Lib/test/test_defaultdict_jy.py
+++ b/Lib/test/test_defaultdict_jy.py
@@ -94,8 +94,38 @@
         self.assertEquals(d.items(), [("vivify", [])]) 
 
 
+class KeyDefaultDict(defaultdict):
+    """defaultdict to pass the requested key to factory function."""
+    def __missing__(self, key):
+        if self.default_factory is None:
+            raise KeyError("Invalid key '{0}' and no default factory was set")
+        else:
+            val = self.default_factory(key)
+
+        self[key] = val
+        return val
+
+    @classmethod
+    def double(cls, k):
+        return k + k
+
+class OverrideMissingTestCase(unittest.TestCase):
+    def test_dont_call_derived_missing(self):
+        kdd = KeyDefaultDict(KeyDefaultDict.double)
+        kdd[3] = 5
+        self.assertEquals(kdd[3], 5)
+
+    #http://bugs.jython.org/issue2088
+    def test_override_missing(self):
+
+        kdd = KeyDefaultDict(KeyDefaultDict.double)
+        # line below causes KeyError in Jython, ignoring overridden __missing__ method
+        self.assertEquals(kdd[3], 6)
+        self.assertEquals(kdd['ab'], 'abab')
+
+
 def test_main():
-    test_support.run_unittest(PickleTestCase, ThreadSafetyTestCase, GetVariantsTestCase)
+    test_support.run_unittest(PickleTestCase, ThreadSafetyTestCase, GetVariantsTestCase, OverrideMissingTestCase)
 
 
 if __name__ == '__main__':
diff --git a/src/org/python/modules/_collections/PyDefaultDict.java b/src/org/python/modules/_collections/PyDefaultDict.java
--- a/src/org/python/modules/_collections/PyDefaultDict.java
+++ b/src/org/python/modules/_collections/PyDefaultDict.java
@@ -167,6 +167,14 @@
     @ExposedMethod(doc = BuiltinDocs.dict___getitem___doc)
     protected final PyObject defaultdict___getitem__(PyObject key) {
         try {
+            PyType type = getType();
+            if (!getMap().containsKey(key) && type != TYPE) {
+                // is a subclass. if it exists call the subclasses __missing__
+                PyObject missing = type.lookup("__missing__");
+                if (missing != null) {
+                    return missing.__get__(this, type).__call__(key);
+                }
+            }
             return backingMap.get(key);
         } catch (Exception ex) {
             throw Py.KeyError(key);

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list