Index: src/org/python/core/PyType.java =================================================================== --- src/org/python/core/PyType.java (revision 7067) +++ src/org/python/core/PyType.java (working copy) @@ -22,6 +22,9 @@ import org.python.modules._weakref.WeakrefModule; import org.python.util.Generic; +import com.google.common.collect.MapMaker; +import java.util.concurrent.ConcurrentMap; + /** * The Python Type object implementation. */ @@ -96,8 +99,8 @@ private static final MethodCache methodCache = new MethodCache(); /** Mapping of Java classes to their PyTypes. */ - private static Map, PyType> class_to_type; - + private static ConcurrentMap, PyType> class_to_type; + /** Mapping of Java classes to their TypeBuilders. */ private static Map, TypeBuilder> classToBuilder; @@ -121,7 +124,15 @@ PyObject[] args, String[] keywords) { // Special case: type(x) should return x.getType() if (args.length == 1 && keywords.length == 0) { - return args[0].getType(); + PyObject obj = args[0]; + PyType objType = obj.getType(); + + // special case for PyStringMap so that it types as a dict + PyType psmType = PyType.fromClass(PyStringMap.class); + if (objType == psmType) { + return PyDictionary.TYPE; + } + return objType; } // If that didn't trigger, we need 3 arguments. but ArgParser below may give a msg // saying type() needs exactly 3. @@ -1251,11 +1262,14 @@ return newtype; } - // XXX what's the proper scope of this synchronization? given module import lock, might be - // ok to omit this sync here... + // re the synchronization used here: this result is cached in each type obj, + // so we just need to prevent data races. all public methods that access class_to_type + // are themselves synchronized. However, if we use Google Collections/Guava, + // MapMaker only uses ConcurrentMap anyway + public static synchronized PyType fromClass(Class c) { if (class_to_type == null) { - class_to_type = Generic.synchronizedWeakHashMap(); + class_to_type = new MapMaker().weakKeys().weakValues().makeMap(); addFromClass(PyType.class, null); } PyType type = class_to_type.get(c); Index: src/org/python/modules/zipimport/zipimporter.java =================================================================== --- src/org/python/modules/zipimport/zipimporter.java (revision 7067) +++ src/org/python/modules/zipimport/zipimporter.java (working copy) @@ -117,7 +117,7 @@ zipimport._zip_directory_cache.__setitem__(archive, files); } } else { - throw zipimport.ZipImportError("not a Zip file"); + throw zipimport.ZipImportError("not a Zip file: " + path); } if (prefix != "" && !prefix.endsWith(File.separator)) { Index: src/org/python/util/Generic.java =================================================================== --- src/org/python/util/Generic.java (revision 7067) +++ src/org/python/util/Generic.java (working copy) @@ -58,11 +58,6 @@ return new HashMap(); } - public static Map synchronizedWeakHashMap() { - return Collections.synchronizedMap(new WeakHashMap()); - } - - /** * Makes a ConcurrentMap using generic types inferred from whatever this is being * assigned to. Index: build.xml =================================================================== --- build.xml (revision 7067) +++ build.xml (working copy) @@ -188,6 +188,7 @@ + @@ -584,6 +585,8 @@ + +