From jython-checkins at python.org Mon Aug 7 15:41:09 2017 From: jython-checkins at python.org (jeff.allen) Date: Mon, 07 Aug 2017 19:41:09 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Restore_thread-safety_of_P?= =?utf-8?q?yType=2EfromClass_in_order_to_fix_=232609=2E?= Message-ID: <20170807194107.81572.5B81770F23D54CEA@psf.io> https://hg.python.org/jython/rev/b03972313073 changeset: 8121:b03972313073 user: Jeff Allen date: Mon Aug 07 20:03:17 2017 +0100 summary: Restore thread-safety of PyType.fromClass in order to fix #2609. This partially backs out cffe5b824a21, to restore synchronisation, but keeps the IOD singleton pattern to protect the type registry. It backs out f3458ef83e08, now unnecessary with PyType synchronised. See also discussion in #2487. files: NEWS | 3 +- src/org/python/core/Deriveds.java | 8 - src/org/python/core/PyType.java | 184 +++++++++-------- 3 files changed, 104 insertions(+), 91 deletions(-) diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -2,8 +2,9 @@ For more details, please see https://hg.python.org/jython -Jython 2.7.2b1 +Development tip Bugs fixed + - [ 2609 ] PyType.fromClass publication race (discovered in strptime and re) - [ 2608 ] Encoding problems with non-ascii host name - [ 2599 ] Cannot handle network paths under Windows - [ 2600 ] subprocess doesn't have _args_from_interpreter_flags (blocks support for multiprocessing) diff --git a/src/org/python/core/Deriveds.java b/src/org/python/core/Deriveds.java --- a/src/org/python/core/Deriveds.java +++ b/src/org/python/core/Deriveds.java @@ -46,14 +46,6 @@ // pass through to __getattr__ } else { PyObject getattribute = type.lookup("__getattribute__"); - // This is a horrible hack for eventual consistency of the cache. We hope that the cached version - // becomes available, but don't wait forever. - for (int i = 0; i < 100000; i++) { - if (getattribute != null) { - break; - } - getattribute = type.lookup("__getattribute__"); - } if (getattribute == null) { // This shouldn't happen throw Py.SystemError(String.format( diff --git a/src/org/python/core/PyType.java b/src/org/python/core/PyType.java --- a/src/org/python/core/PyType.java +++ b/src/org/python/core/PyType.java @@ -28,7 +28,11 @@ import com.google.common.collect.MapMaker; /** - * The Python Type object implementation. + * The Python type object implementation. + *

+ * The class PyType contains static data that describes Python types that is consulted + * and modified through its static API (notably {@link #fromClass(Class)}). The data structures are + * guarded against modification (or consultation while being modified) by concurrent threads. */ @ExposedType(name = "type", doc = BuiltinDocs.type_doc) public class PyType extends PyObject implements Serializable, Traverseproc { @@ -100,8 +104,57 @@ private transient ReferenceQueue subclasses_refq = new ReferenceQueue(); private Set> subclasses = Generic.linkedHashSet(); - /** Global mro cache. */ - private static final MethodCache methodCache = new MethodCache(); + /** + * The class PyType contains static data that describes Python types though a + * system of indexes and PyType objects. Each PyObject calls + * {@link PyType#fromClass(Class)}, which adds to this data, as it is being initialised. The + * PyType static data must be valid (consistent) ready to handle that call. + *

+ * PyType itself is a PyObject calls {@link PyType#fromClass(Class)} + * during initialisation. In order to guarantee that the static state of PyType is + * valid at that point, it has to be in a separate class, here privately nested. See the classic + * "The + * double-checked locking problem", which we use here to be prompt rather than lazy. + *

+ * A further consequence is that the data structures must be guarded against concurrent + * modification (or modification and access). + */ + /* + * We aspire to a design in which a PyType for a Class could be got and used, in a thread-safe + * way, without synchronisation on the static state as a whole. This would let us have + * fine-grained locking (maybe only on PyType). The semantics of ClassValue are probably what we + * need: the PyType exists until the Java class is unloaded. ClassValue might not be sufficient + * if we wished to permit collection of PyTypes we won't use again, for Java classes that remain + * in use, and we can identify them. + */ + private static final class StaticMaps { + + /** Mapping of Java classes to their PyTypes. */ + private static final ConcurrentMap, PyType> classToType = + new MapMaker().weakKeys().weakValues().makeMap(); + + /** Types that should not be garbage-collected (see {@link #fromClass(Class, boolean)} */ + private static final Set exposedTypes = Generic.set(); + + /** Mapping of Java classes to their TypeBuilders. */ + private static final ConcurrentMap, TypeBuilder> classToBuilder = + Generic.concurrentMap(); + } + + /** Mapping of Java classes to their PyTypes. */ + private static ConcurrentMap, PyType> getClassToType() { + return StaticMaps.classToType; + } + + /** Types that should not be garbage-collected (see {@link #fromClass(Class, boolean)} */ + private static Set getExposedTypes() { + return StaticMaps.exposedTypes; + } + + /** Mapping of Java classes to their TypeBuilders. */ + private static ConcurrentMap, TypeBuilder> getClassToBuilder() { + return StaticMaps.classToBuilder; + } protected PyType(PyType subtype) { super(subtype); @@ -1360,13 +1413,7 @@ * @return found object or null */ public PyObject lookup_where(String name, PyObject[] where) { - /* Can we even switch to an assert here? - * assert methodCache != null; - */ - if (methodCache == null) { - Py.warning(Py.RuntimeWarning, "PyType: methodCache is null"); - } - return methodCache.lookup_where(this, name, where); + return MethodCache.methodCache.lookup_where(this, name, where); } /** @@ -1439,12 +1486,11 @@ return null; } - public static void addBuilder(Class forClass, TypeBuilder builder) { + public static synchronized void addBuilder(Class forClass, TypeBuilder builder) { getClassToBuilder().put(forClass, builder); - if (getClassToType().containsKey(forClass)) { if (!BootstrapTypesSingleton.getInstance().remove(forClass)) { - Py.writeWarning("init", "Bootstrapping class not in BootstrapTypesSingleton.getClassToType()[class=" + Py.writeWarning("init", "Bootstrapping class not in BootstrapTypesSingleton.getInstance()[class=" + forClass + "]"); } // The types in BootstrapTypesSingleton.getClassToType() are initialized before their builders are assigned, @@ -1453,7 +1499,7 @@ } } - private static PyType addFromClass(Class c, Set needsInners) { + private synchronized static PyType addFromClass(Class c, Set needsInners) { if (ExposeAsSuperclass.class.isAssignableFrom(c)) { PyType exposedAs = fromClass(c.getSuperclass(), false); PyType origExposedAs = getClassToType().putIfAbsent(c, exposedAs); @@ -1498,8 +1544,8 @@ return builder; } - private static PyType createType(Class c, Set needsInners) { -// System.out.println("createType c=" + c + ", needsInners=" + needsInners + ", BootstrapTypesSingleton.getInstance()=" + BootstrapTypesSingleton.getInstance()); + private synchronized static PyType createType(Class c, Set needsInners) { + // System.out.println("createType c=" + c + ", needsInners=" + needsInners + ", BootstrapTypesSingleton.getInstance()=" + BootstrapTypesSingleton.getInstance()); PyType newtype; if (c == PyType.class) { newtype = new PyType(false); @@ -1509,40 +1555,52 @@ newtype = new PyJavaType(); } - // try to put the type into our cache but if one exists already ignore our new creation and instead return - // existing instance. This saves us from locking the whole createType and instead depend on the - // atomicity of putIfAbsent and finicky ordering :( + /* + * Try to register the type (so far incomplete), but if one has already been registered, use + * that. This is more subtle than it looks: the one we've found may be complete or + * incomplete. If it is incomplete, then because of the lock this thread holds on + * PyType.class, we arrived here by recursion (the Python version of c requires a Python + * version of c), and as long as all intervening calls complete normally, the PyType will be + * properly formed before the lock is released. + */ PyType type = getClassToType().putIfAbsent(c, newtype); - // synchronize on the c here to make sure the compiler does not re-order - synchronized (c) { - if (type != null) { - return type; - } + if (type != null) { + return type; + } - newtype.builtin = true; - newtype.init(c, needsInners); - newtype.invalidateMethodCache(); - return newtype; - } + // This really is a new creation. We need to finish filling it in. + newtype.builtin = true; + newtype.init(c, needsInners); + newtype.invalidateMethodCache(); + return newtype; } - /* - Instead of using synchronization on the whole method we depend on IOD and putIfAbsent behaviour, - essentially letting the first type creation win and throwing away any concurrent ones. - This let's us have much more fine-grained locking. + /** + * Return a PyType (or subclass) for the given Java class, creating one if + * necessary. Equivalent to fromClass(c, true). See + * {@link #fromClass(Class, boolean)}. + * + * @param c for which the corresponding PyType is to be found + * @return the PyType found or created */ - - public static PyType fromClass(Class c) { + public static synchronized PyType fromClass(Class c) { return fromClass(c, true); } - public static PyType fromClass(Class c, boolean hardRef) { + /** + * Return a PyType (or sub-class) for the given Java class, creating one if + * necessary. Creating the PyType also creates any types this depends upon, and + * updates all this in the state internal to PyType that supports future resolution + * of names. + * + * @param c for which the corresponding PyType is to be found + * @param hardRef the PyType will not be unloaded when unreachable + * @return the PyType found or created + */ + public static synchronized PyType fromClass(Class c, boolean hardRef) { PyType type = getClassToType().get(c); if (type != null) { - // synchronize on the c here to make sure the compiler does not re-order - synchronized (c) { - return type; - } + return type; } // We haven't seen this class before, so its type needs to be created. If it's being // exposed as a Java class, defer processing its inner types until it's completely @@ -1577,7 +1635,7 @@ return result; } - static PyType fromClassSkippingInners(Class c, Set needsInners) { + static synchronized PyType fromClassSkippingInners(Class c, Set needsInners) { PyType type = getClassToType().get(c); if (type != null) { return type; @@ -2141,6 +2199,9 @@ */ static class MethodCache { + /** Global mro cache. See {@link PyType#lookup_where(String, PyObject[])}.*/ + private static final MethodCache methodCache = new MethodCache(); + /** The fixed size cache. */ private final AtomicReferenceArray table; @@ -2238,47 +2299,6 @@ } } - /** - * - * Using the IOD http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl - * to reduce the risk for race conditions in a few of our fields - * - */ - - /** - * Mapping of Java classes to their PyTypes. - */ - private static class LazyClassToTypeHolder { - private static ConcurrentMap, PyType> classToType = new MapMaker().weakKeys().weakValues().makeMap(); - - } - - private static ConcurrentMap, PyType> getClassToType() { - return LazyClassToTypeHolder.classToType; - } - - /** - * Mapping of Java classes to their TypeBuilders. - */ - private static class LazyClassToBuilderHolder { - private static ConcurrentMap, TypeBuilder> classToBuilder = Generic.concurrentMap(); - } - - private static ConcurrentMap, TypeBuilder> getClassToBuilder() { - return LazyClassToBuilderHolder.classToBuilder; - } - - /** - * Set of exposed types - */ - private static class LazyExposedTypes { - private static Set exposedTypes = Generic.set(); - } - - private static Set getExposedTypes() { - return LazyExposedTypes.exposedTypes; - } - /* Traverseproc implementation */ @Override public int traverse(Visitproc visit, Object arg) { -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Aug 27 07:45:40 2017 From: jython-checkins at python.org (jeff.allen) Date: Sun, 27 Aug 2017 11:45:40 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Avoid_NPE_in_imp=2Ejava_du?= =?utf-8?q?e_to_encoding_null_directory_name=2E_Fixes_=232612=2E?= Message-ID: <20170827114540.92642.318A5810E8B4904A@psf.io> https://hg.python.org/jython/rev/39b0bd0dcd01 changeset: 8123:39b0bd0dcd01 user: Jeff Allen date: Sun Aug 27 12:40:25 2017 +0100 summary: Avoid NPE in imp.java due to encoding null directory name. Fixes #2612. This was a regresion caused when trying to deal with non-ascii paths in the preparation of a log message. Thanks to James Mudd for diagnosing this. Also https://github.com/jythontools/jython/pull/86. files: NEWS | 1 + src/org/python/core/PyString.java | 2 +- src/org/python/core/imp.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ Development tip Bugs fixed + - [ 2612 ] NPE while trying to load class - [ 2609 ] PyType.fromClass publication race (discovered in strptime and re) - [ 2608 ] Encoding problems with non-ascii host name - [ 2599 ] Cannot handle network paths under Windows diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -316,7 +316,7 @@ * @param quoteChar '"' or '\'' use that, '?' = let Python choose, 0 or anything = no quotes * @return encoded string (possibly the same string if unchanged) */ - public static String encode_UnicodeEscape(String str, char quote) { + static String encode_UnicodeEscape(String str, char quote) { // Choose whether to quote and the actual quote character boolean use_quotes; diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -624,7 +624,7 @@ if (caseok(dir, name) && (sourceFile.isFile() || compiledFile.isFile())) { pkg = true; } else { - String printDirName = PyString.encode_UnicodeEscape(displayDirName, '\''); + String printDirName = PyString.encode_UnicodeEscape(dir.getPath(), '\''); Py.warning(Py.ImportWarning, String.format( "Not importing directory %s: missing __init__.py", printDirName)); } -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Aug 27 07:45:40 2017 From: jython-checkins at python.org (jeff.allen) Date: Sun, 27 Aug 2017 11:45:40 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Formatting_changes_only_to?= =?utf-8?q?_PyType_and_PyJavaType_=28avoiding_noise_later=29=2E?= Message-ID: <20170827114540.90858.3492416D46A9A8D6@psf.io> https://hg.python.org/jython/rev/60f8e7bc678e changeset: 8122:60f8e7bc678e user: Jeff Allen date: Tue Aug 08 07:11:16 2017 +0100 summary: Formatting changes only to PyType and PyJavaType (avoiding noise later). files: src/org/python/core/PyJavaType.java | 376 ++++--- src/org/python/core/PyType.java | 771 ++++++++------- 2 files changed, 657 insertions(+), 490 deletions(-) diff --git a/src/org/python/core/PyJavaType.java b/src/org/python/core/PyJavaType.java --- a/src/org/python/core/PyJavaType.java +++ b/src/org/python/core/PyJavaType.java @@ -15,6 +15,7 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -24,7 +25,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Queue; @@ -34,25 +34,27 @@ import org.python.core.util.StringUtil; import org.python.util.Generic; - public class PyJavaType extends PyType { private final static Class[] OO = {PyObject.class, PyObject.class}; + // @formatter:off /** Deprecated methods in java.awt.* that have bean property equivalents we prefer. */ - private final static Set BAD_AWT_METHODS = Generic.set("layout", - "insets", - "size", - "minimumSize", - "preferredSize", - "maximumSize", - "bounds", - "enable"); - - - // Add well-known immutable classes from standard packages of - // java.lang, java.net, java.util that are not marked Cloneable. - // This was found by hand, there are likely more! + private final static Set BAD_AWT_METHODS = Generic.set( + "layout", + "insets", + "size", + "minimumSize", + "preferredSize", + "maximumSize", + "bounds", + "enable"); + // @formatter:on + /* + * Add well-known immutable classes from standard packages of java.lang, java.net, java.util + * that are not marked Cloneable. This was found by hand, there are likely more! + */ + // @formatter:off private final static Set> immutableClasses = Generic.set( Boolean.class, Byte.class, @@ -71,7 +73,7 @@ java.net.Proxy.class, java.net.URI.class, java.util.concurrent.TimeUnit.class); - + // @formatter:on /** * Other Java classes this type has MRO conflicts with. This doesn't matter for Java method @@ -98,14 +100,15 @@ @Override protected boolean useMetatypeFirst(PyObject attr) { - return !(attr instanceof PyReflectedField || attr instanceof PyReflectedFunction || - attr instanceof PyBeanEventProperty); + return !(attr instanceof PyReflectedField || attr instanceof PyReflectedFunction + || attr instanceof PyBeanEventProperty); } // Java types are ok with things being added and removed from their dicts as long as there isn't @Override void type___setattr__(String name, PyObject value) { - PyObject field = lookup(name);// If we have a static field that takes this, go with that + PyObject field = lookup(name); + // If we have a static field that takes this, go with that if (field != null) { if (field._doset(null, value)) { return; @@ -134,7 +137,7 @@ void type___delattr__(String name) { PyObject field = lookup(name); if (field == null) { - throw Py.NameError("attribute not found: "+name); + throw Py.NameError("attribute not found: " + name); } if (!field.jdontdel()) { object___delattr__(name); @@ -160,13 +163,15 @@ continue; } if (winner == null) { - // Pick an arbitrary class to be added to the mro next and break the conflict. - // If method name conflicts were allowed between methods added to Java types, - // it would go first, but that's prevented, so being a winner doesn't actually - // get it anything - winner = (PyJavaType)mergee.mro[i]; + /* + * Pick an arbitrary class to be added to the mro next and break the conflict. + * If method name conflicts were allowed between methods added to Java types, it + * would go first, but that's prevented, so being a winner doesn't actually get + * it anything. + */ + winner = (PyJavaType) mergee.mro[i]; } - inConflict.add((PyJavaType)mergee.mro[i]); + inConflict.add((PyJavaType) mergee.mro[i]); } } @@ -177,7 +182,8 @@ continue; } for (String method : type.modified) { - if (!allModified.add(method)) { // Another type in conflict has this method, possibly fail + if (!allModified.add(method)) { + // Another type in conflict has this method, possibly fail PyList types = new PyList(); Set> proxySet = Generic.set(); for (PyJavaType othertype : conflictedAttributes) { @@ -186,22 +192,28 @@ proxySet.add(othertype.getProxyType()); } } - // Need to special case collections that implement both Iterable and Map. Ignore the conflict - // in having duplicate __iter__ added (see getCollectionProxies), while still allowing each - // path on the inheritance hierarchy to get an __iter__. Annoying but necessary logic. - // See http://bugs.jython.org/issue1878 - if (method.equals("__iter__") && proxySet.equals(Generic.set(Iterable.class, Map.class))) { + /* + * Need to special case collections that implement both Iterable and Map. Ignore + * the conflict in having duplicate __iter__ added (see getCollectionProxies), + * while still allowing each path on the inheritance hierarchy to get an + * __iter__. Annoying but necessary logic. See http://bugs.jython.org/issue1878 + */ + if (method.equals("__iter__") + && proxySet.equals(Generic.set(Iterable.class, Map.class))) { continue; } - throw Py.TypeError(String.format("Supertypes that share a modified attribute " - + "have an MRO conflict[attribute=%s, supertypes=%s, type=%s]", + throw Py.TypeError(String.format( + "Supertypes that share a modified attribute " + + "have an MRO conflict[attribute=%s, supertypes=%s, type=%s]", method, types, this.getName())); } } } - // We can keep trucking, there aren't any existing method name conflicts. Mark the - // conflicts in all the classes so further method additions can check for trouble + /* + * We can keep trucking, there aren't any existing method name conflicts. Mark the conflicts + * in all the classes so further method additions can check for trouble. + */ for (PyJavaType type : conflictedAttributes) { for (PyJavaType otherType : inConflict) { if (otherType != type) { @@ -231,28 +243,36 @@ dict = new PyStringMap(); Class baseClass = forClass.getSuperclass(); if (PyObject.class.isAssignableFrom(forClass)) { - // Non-exposed subclasses of PyObject use a simple linear mro to PyObject that ignores - // their interfaces + /* + * Non-exposed subclasses of PyObject use a simple linear mro to PyObject that ignores + * their interfaces. + */ underlying_class = forClass; computeLinearMro(baseClass); } else { needsInners.add(this); JyAttribute.setAttr(this, JyAttribute.JAVA_PROXY_ATTR, forClass); objtype = PyType.fromClassSkippingInners(Class.class, needsInners); - // Wrapped Java types fill in their mro first using all of their interfaces then their - // super class. + /* + * Wrapped Java types fill in their mro first using all of their interfaces then their + * super class. + */ List visibleBases = Generic.list(); for (Class iface : forClass.getInterfaces()) { if (iface == PyProxy.class || iface == ClassDictInit.class) { - // Don't show the interfaces added by proxy type construction; otherwise Python - // subclasses of proxy types and another Java interface can't make a consistent - // mro + /* + * Don't show the interfaces added by proxy type construction; otherwise Python + * subclasses of proxy types and another Java interface can't make a consistent + * mro. + */ continue; } if (baseClass != null && iface.isAssignableFrom(baseClass)) { - // Don't include redundant interfaces. If the redundant interface has methods - // that were combined with methods of the same name from other interfaces higher - // in the hierarchy, adding it here hides the forms from those interfaces. + /* + * Don't include redundant interfaces. If the redundant interface has methods + * that were combined with methods of the same name from other interfaces higher + * in the hierarchy, adding it here hides the forms from those interfaces. + */ continue; } visibleBases.add(PyType.fromClassSkippingInners(iface, needsInners)); @@ -262,7 +282,7 @@ if (javaProxy == Object.class) { base = PyType.fromClassSkippingInners(PyObject.class, needsInners); - } else if(baseClass == null) { + } else if (baseClass == null) { base = PyType.fromClassSkippingInners(Object.class, needsInners); } else if (javaProxy == Class.class) { base = PyType.fromClassSkippingInners(PyType.class, needsInners); @@ -274,10 +294,12 @@ mro = computeMro(); } - // PyReflected* can't call or access anything from non-public classes that aren't in - // org.python.core - if (!Modifier.isPublic(forClass.getModifiers()) && - !name.startsWith("org.python.core") && Options.respectJavaAccessibility) { + /* + * PyReflected* can't call or access anything from non-public classes that aren't in + * org.python.core + */ + if (!Modifier.isPublic(forClass.getModifiers()) && !name.startsWith("org.python.core") + && Options.respectJavaAccessibility) { handleSuperMethodArgCollisions(forClass); return; } @@ -292,7 +314,7 @@ } else { // Grab all methods on this class and all of its superclasses and make them accessible List allMethods = Generic.list(); - for(Class c = forClass; c != null; c = c.getSuperclass()) { + for (Class c = forClass; c != null; c = c.getSuperclass()) { for (Method meth : c.getDeclaredMethods()) { allMethods.add(meth); meth.setAccessible(true); @@ -301,7 +323,7 @@ methods = allMethods.toArray(new Method[allMethods.size()]); } - /* make sure we "sort" all methods so they resolve in the right order. See #2391 for details */ + // Make sure we sort all methods so they resolve in the right order. See #2391 for detail. Arrays.sort(methods, new MethodComparator(new ClassComparator())); boolean isInAwt = name.startsWith("java.awt.") && name.indexOf('.', 9) == -1; @@ -314,9 +336,11 @@ String methname = meth.getName(); - // Special case a few troublesome methods in java.awt.*. These methods are all - // deprecated and interfere too badly with bean properties to be tolerated. This is - // totally a hack but a lot of code that uses java.awt will break without it. + /* + * Special case a few troublesome methods in java.awt.*. These methods are all + * deprecated and interfere too badly with bean properties to be tolerated. This is + * totally a hack but a lot of code that uses java.awt will break without it. + */ if (isInAwt && BAD_AWT_METHODS.contains(methname)) { continue; } @@ -339,9 +363,8 @@ // First check if this is a bean event addition method int n = meth.getParameterTypes().length; if ((methname.startsWith("add") || methname.startsWith("set")) - && methname.endsWith("Listener") && n == 1 && - meth.getReturnType() == Void.TYPE && - EventListener.class.isAssignableFrom(meth.getParameterTypes()[0])) { + && methname.endsWith("Listener") && n == 1 && meth.getReturnType() == Void.TYPE + && EventListener.class.isAssignableFrom(meth.getParameterTypes()[0])) { Class eventClass = meth.getParameterTypes()[0]; String ename = eventClass.getName(); int idot = ename.lastIndexOf('.'); @@ -377,11 +400,12 @@ prop.myType = meth.getReturnType(); } else { prop.setMethod = meth; - // Needed for readonly properties. Getter will be used instead - // if there is one. Only works if setX method has exactly one - // param, which is the only reasonable case. - // XXX: should we issue a warning if setX and getX have different - // types? + /* + * Needed for readonly properties. Getter will be used instead if there is one. + * Only works if setX method has exactly one param, which is the only reasonable + * case. + */ + // XXX: should we issue a warning if setX and getX have different types? if (prop.myType == null) { Class[] params = meth.getParameterTypes(); if (params.length == 1) { @@ -397,15 +421,19 @@ String nmethname = normalize(meth.getName()); reflfunc = (PyReflectedFunction) dict.__finditem__(nmethname); if (reflfunc != null) { - // The superclass method has the same name as one declared on this class, so add - // the superclass version's arguments + /* + * The superclass method has the same name as one declared on this class, so add the + * superclass version's arguments. + */ reflfunc.addMethod(meth); } else if (PyReflectedFunction.isPackagedProtected(meth.getDeclaringClass()) && lookup(nmethname) == null) { - // This method must be a public method from a package protected superclass. It's - // visible from Java on this class, so do the same for Python here. This is the - // flipside of what handleSuperMethodArgCollisions does for inherited public methods - // on package protected classes. + /* + * This method must be a public method from a package protected superclass. It's + * visible from Java on this class, so do the same for Python here. This is the + * flipside of what handleSuperMethodArgCollisions does for inherited public methods + * on package protected classes. + */ reflfunc = new PyReflectedFunction(meth); reflectedFuncs.add(reflfunc); dict.__setitem__(nmethname, reflfunc); @@ -440,8 +468,8 @@ } catch (IllegalAccessException e) { throw Py.JavaError(e); } - ((PyReflectedFunction)memb).__doc__ = doc instanceof PyString ? - (PyString) doc : new PyString(doc.toString()); + ((PyReflectedFunction) memb).__doc__ = doc instanceof PyString + ? (PyString) doc : new PyString(doc.toString()); } } } @@ -460,10 +488,8 @@ if (dict.__finditem__(methodName) != null) { continue; } - dict.__setitem__(methodName, new PyBeanEventProperty(methodName, - ev.eventClass, - ev.addMethod, - meth)); + dict.__setitem__(methodName, + new PyBeanEventProperty(methodName, ev.eventClass, ev.addMethod, meth)); } } @@ -472,30 +498,36 @@ PyObject prev = dict.__finditem__(prop.__name__); if (prev != null) { if (!(prev instanceof PyReflectedField) - || !Modifier.isStatic(((PyReflectedField)prev).field.getModifiers())) { + || !Modifier.isStatic(((PyReflectedField) prev).field.getModifiers())) { // Any methods or non-static fields take precedence over the bean property continue; } else { // Must've been a static field, so add it to the property - prop.field = ((PyReflectedField)prev).field; + prop.field = ((PyReflectedField) prev).field; } } - // If one of our superclasses has something defined for this name, check if its a bean - // property, and if so, try to fill in any gaps in our property from there - PyObject fromType[] = new PyObject[] { null }; + /* + * If one of our superclasses has something defined for this name, check if its a bean + * property, and if so, try to fill in any gaps in our property from there. + */ + PyObject fromType[] = new PyObject[] {null}; PyObject superForName = lookup_where_mro(prop.__name__, fromType); if (superForName instanceof PyBeanProperty) { - PyBeanProperty superProp = ((PyBeanProperty)superForName); - // If it has a set method and we don't, take it regardless. If the types don't line - // up, it'll be rejected below + PyBeanProperty superProp = ((PyBeanProperty) superForName); + /* + * If it has a set method and we don't, take it regardless. If the types don't line + * up, it'll be rejected below. + */ if (prop.setMethod == null) { prop.setMethod = superProp.setMethod; } else if (prop.getMethod == null - && superProp.myType == prop.setMethod.getParameterTypes()[0]) { - // Only take a get method if the type on it agrees with the set method - // we already have. The bean on this type overrides a conflicting one - // of the parent + && superProp.myType == prop.setMethod.getParameterTypes()[0]) { + /* + * Only take a get method if the type on it agrees with the set method we + * already have. The bean on this type overrides a conflicting one of the + * parent. + */ prop.getMethod = superProp.getMethod; prop.myType = superProp.myType; } @@ -504,15 +536,19 @@ // If the parent bean is hiding a static field, we need it as well. prop.field = superProp.field; } - } else if (superForName != null && fromType[0] != this && !(superForName instanceof PyBeanEvent)) { - // There is already an entry for this name - // It came from a type which is not @this; it came from a superclass - // It is not a bean event - // Do not override methods defined in superclass + } else if (superForName != null && fromType[0] != this + && !(superForName instanceof PyBeanEvent)) { + /* + * There is already an entry for this name. It came from a type which is not @this; + * it came from a superclass. It is not a bean event. Do not override methods + * defined in superclass. + */ continue; } - // If the return types on the set and get methods for a property don't agree, the get - // method takes precedence + /* + * If the return types on the set and get methods for a property don't agree, the get + * method takes precedence. + */ if (prop.getMethod != null && prop.setMethod != null && prop.myType != prop.setMethod.getParameterTypes()[0]) { prop.setMethod = null; @@ -522,8 +558,10 @@ final PyReflectedConstructor reflctr = new PyReflectedConstructor(name); Constructor[] constructors; - // No matter the security manager, trying to set the constructor on class to accessible - // blows up + /* + * No matter the security manager, trying to set the constructor on class to accessible + * blows up. + */ if (Options.respectJavaAccessibility || Class.class == forClass) { // returns just the public constructors constructors = forClass.getConstructors(); @@ -538,10 +576,10 @@ } if (PyObject.class.isAssignableFrom(forClass)) { PyObject new_ = new PyNewWrapper(forClass, "__new__", -1, -1) { - @Override public PyObject new_impl(boolean init, - PyType subtype, - PyObject[] args, - String[] keywords) { + + @Override + public PyObject new_impl(boolean init, PyType subtype, PyObject[] args, + String[] keywords) { return reflctr.make(args, keywords); } }; @@ -584,7 +622,7 @@ if (nameSpecified == null) { nameSpecified = Py.newString(name); } - for (PyReflectedFunction func: reflectedFuncs) { + for (PyReflectedFunction func : reflectedFuncs) { func.__module__ = nameSpecified; } } @@ -601,20 +639,27 @@ if (forClass == Object.class) { addMethod(new PyBuiltinMethodNarrow("__copy__") { + @Override public PyObject __call__() { - throw Py.TypeError("Could not copy Java object because it is not Cloneable or known to be immutable. " - + "Consider monkeypatching __copy__ for " + self.getType().fastGetName()); + throw Py.TypeError( + "Could not copy Java object because it is not Cloneable or known to be immutable. " + + "Consider monkeypatching __copy__ for " + + self.getType().fastGetName()); } }); addMethod(new PyBuiltinMethodNarrow("__deepcopy__") { + @Override public PyObject __call__(PyObject memo) { - throw Py.TypeError("Could not deepcopy Java object because it is not Serializable. " - + "Consider monkeypatching __deepcopy__ for " + self.getType().fastGetName()); + throw Py.TypeError( + "Could not deepcopy Java object because it is not Serializable. " + + "Consider monkeypatching __deepcopy__ for " + + self.getType().fastGetName()); } }); addMethod(new PyBuiltinMethodNarrow("__eq__", 1) { + @Override public PyObject __call__(PyObject o) { Object proxy = self.getJavaProxy(); @@ -623,6 +668,7 @@ } }); addMethod(new PyBuiltinMethodNarrow("__ne__", 1) { + @Override public PyObject __call__(PyObject o) { Object proxy = self.getJavaProxy(); @@ -631,12 +677,14 @@ } }); addMethod(new PyBuiltinMethodNarrow("__hash__") { + @Override public PyObject __call__() { return Py.newInteger(self.getJavaProxy().hashCode()); } }); addMethod(new PyBuiltinMethodNarrow("__repr__") { + @Override public PyObject __call__() { /* @@ -648,6 +696,7 @@ } }); addMethod(new PyBuiltinMethodNarrow("__unicode__") { + @Override public PyObject __call__() { return new PyUnicode(self.toString()); @@ -655,26 +704,30 @@ }); } - if(forClass == Comparable.class) { + if (forClass == Comparable.class) { addMethod(new ComparableMethod("__lt__", 1) { + @Override protected boolean getResult(int comparison) { return comparison < 0; } }); addMethod(new ComparableMethod("__le__", 1) { + @Override protected boolean getResult(int comparison) { return comparison <= 0; } }); addMethod(new ComparableMethod("__gt__", 1) { + @Override protected boolean getResult(int comparison) { return comparison > 0; } }); addMethod(new ComparableMethod("__ge__", 1) { + @Override protected boolean getResult(int comparison) { return comparison >= 0; @@ -685,6 +738,7 @@ if (immutableClasses.contains(forClass)) { // __deepcopy__ just works for these objects since it uses serialization instead addMethod(new PyBuiltinMethodNarrow("__copy__") { + @Override public PyObject __call__() { return self; @@ -692,17 +746,20 @@ }); } - if(forClass == Cloneable.class) { + if (forClass == Cloneable.class) { addMethod(new PyBuiltinMethodNarrow("__copy__") { + @Override public PyObject __call__() { Object obj = self.getJavaProxy(); Method clone; - // TODO we could specialize so that for well known objects like collections. - // This would avoid needing to use reflection in the general case, - // because Object#clone is protected (but most subclasses are not). - // - // Lastly we can potentially cache the method handle in the proxy instead of looking it up each time + /* + * TODO we could specialize so that for well known objects like collections. + * This would avoid needing to use reflection in the general case, because + * Object#clone is protected (but most subclasses are not). Lastly we can + * potentially cache the method handle in the proxy instead of looking it up + * each time + */ try { clone = obj.getClass().getMethod("clone"); Object copy = clone.invoke(obj); @@ -714,8 +771,9 @@ }); } - if(forClass == Serializable.class) { + if (forClass == Serializable.class) { addMethod(new PyBuiltinMethodNarrow("__deepcopy__") { + @Override public PyObject __call__(PyObject memo) { Object obj = self.getJavaProxy(); @@ -730,10 +788,11 @@ } } - // cloneX, CloneOutput, CloneInput are verbatim from Eamonn McManus' - // http://weblogs.java.net/blog/emcmanus/archive/2007/04/cloning_java_ob.html - // blog post on deep cloning through serialization - - // just what we need for __deepcopy__ support of Java objects + /* + * cloneX, CloneOutput, CloneInput are verbatim from Eamonn McManus' + * http://weblogs.java.net/blog/emcmanus/archive/2007/04/cloning_java_ob.html blog post on deep + * cloning through serialization - just what we need for __deepcopy__ support of Java objects + */ private static T cloneX(T x) throws IOException, ClassNotFoundException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); CloneOutput cout = new CloneOutput(bout); @@ -750,6 +809,7 @@ } private static class CloneOutput extends ObjectOutputStream { + Queue> classQueue = new LinkedList>(); CloneOutput(OutputStream out) throws IOException { @@ -768,6 +828,7 @@ } private static class CloneInput extends ObjectInputStream { + private final CloneOutput output; CloneInput(InputStream in, CloneOutput output) throws IOException { @@ -782,8 +843,8 @@ String expected = osc.getName(); String found = (c == null) ? null : c.getName(); if (!expected.equals(found)) { - throw new InvalidClassException("Classes desynchronized: " + - "found " + found + " when expecting " + expected); + throw new InvalidClassException("Classes desynchronized: " + "found " + found + + " when expecting " + expected); } return c; } @@ -817,8 +878,10 @@ if (forClass.getSuperclass() != null) { mergeMethods(forClass.getSuperclass()); if (!Modifier.isPublic(forClass.getSuperclass().getModifiers())) { - // If the superclass is also not public, it needs to get the same treatment as we - // can't call its methods either. + /* + * If the superclass is also not public, it needs to get the same treatment as we + * can't call its methods either. + */ handleSuperMethodArgCollisions(forClass.getSuperclass()); } } @@ -834,29 +897,34 @@ PyObject[] where = new PyObject[1]; PyObject obj = lookup_where_mro(nmethname, where); if (obj == null) { - // Nothing in our supertype hierarchy defines something with this name, so it - // must not be visible there. + /* + * Nothing in our supertype hierarchy defines something with this name, so it must + * not be visible there. + */ continue; } else if (where[0] == this) { - // This method is the only thing defining items in this class' dict, so it must - // be a PyReflectedFunction created here. See if it needs the current method - // added to it. - if (!((PyReflectedFunction)obj).handles(meth)) { - ((PyReflectedFunction)obj).addMethod(meth); + /* + * This method is the only thing defining items in this class' dict, so it must be a + * PyReflectedFunction created here. See if it needs the current method added to it. + */ + if (!((PyReflectedFunction) obj).handles(meth)) { + ((PyReflectedFunction) obj).addMethod(meth); } } else { - // There's something in a superclass with the same name. Add an item to this type's - // dict to hide it. If it's this method, nothing's changed. If it's a field, we - // want to make the method visible. If it's a different method, it'll be added to - // the reflected function created here in a later call. + /* + * There's something in a superclass with the same name. Add an item to this type's + * dict to hide it. If it's this method, nothing's changed. If it's a field, we want + * to make the method visible. If it's a different method, it'll be added to the + * reflected function created here in a later call. + */ dict.__setitem__(nmethname, new PyReflectedFunction(meth)); } } } private static boolean declaredOnMember(Class base, Member declaring) { - return base == null || (declaring.getDeclaringClass() != base && - base.isAssignableFrom(declaring.getDeclaringClass())); + return base == null || (declaring.getDeclaringClass() != base + && base.isAssignableFrom(declaring.getDeclaringClass())); } private static String normalize(String name) { @@ -890,12 +958,14 @@ } private static class EnumerationIter extends PyIterator { + private Enumeration proxy; public EnumerationIter(Enumeration proxy) { this.proxy = proxy; } + @Override public PyObject __iternext__() { return proxy.hasMoreElements() ? Py.java2py(proxy.nextElement()) : null; } @@ -913,8 +983,8 @@ Object asjava = arg.__tojava__(Object.class); int compare; try { - compare = ((Comparable)self.getJavaProxy()).compareTo(asjava); - } catch(ClassCastException classCast) { + compare = ((Comparable) self.getJavaProxy()).compareTo(asjava); + } catch (ClassCastException classCast) { return Py.NotImplemented; } return getResult(compare) ? Py.True : Py.False; @@ -923,10 +993,12 @@ protected abstract boolean getResult(int comparison); } - // Traverseproc-note: Usually we would have to traverse this class, but we can - // leave this out, since CollectionProxies is only used locally in private - // static fields. + /* + * Traverseproc-note: Usually we would have to traverse this class, but we can leave this out, + * since CollectionProxies is only used locally in private static fields. + */ private static class CollectionProxies { + final Map, PyBuiltinMethod[]> proxies; final Map, PyBuiltinMethod[]> postProxies; @@ -937,6 +1009,7 @@ } private static class CollectionsProxiesHolder { + static final CollectionProxies proxies = new CollectionProxies(); } @@ -959,21 +1032,24 @@ final Map, PyBuiltinMethod[]> proxies = new HashMap<>(); PyBuiltinMethodNarrow iterableProxy = new PyBuiltinMethodNarrow("__iter__") { + @SuppressWarnings("unchecked") @Override public PyObject __call__() { return new JavaIterator(((Iterable) self.getJavaProxy())); } }; - proxies.put(Iterable.class, new PyBuiltinMethod[]{iterableProxy}); + proxies.put(Iterable.class, new PyBuiltinMethod[] {iterableProxy}); PyBuiltinMethodNarrow lenProxy = new PyBuiltinMethodNarrow("__len__") { + @Override public PyObject __call__() { return Py.newInteger(((Collection) self.getJavaProxy()).size()); } }; PyBuiltinMethodNarrow containsProxy = new PyBuiltinMethodNarrow("__contains__", 1) { + @Override public PyObject __call__(PyObject obj) { boolean contained = false; @@ -993,25 +1069,27 @@ return contained ? Py.True : Py.False; } }; - proxies.put(Collection.class, new PyBuiltinMethod[]{lenProxy, containsProxy}); + proxies.put(Collection.class, new PyBuiltinMethod[] {lenProxy, containsProxy}); PyBuiltinMethodNarrow iteratorProxy = new PyBuiltinMethodNarrow("__iter__") { + @SuppressWarnings("unchecked") @Override public PyObject __call__() { return new JavaIterator(((Iterator) self.getJavaProxy())); } }; - proxies.put(Iterator.class, new PyBuiltinMethod[]{iteratorProxy}); + proxies.put(Iterator.class, new PyBuiltinMethod[] {iteratorProxy}); PyBuiltinMethodNarrow enumerationProxy = new PyBuiltinMethodNarrow("__iter__") { + @SuppressWarnings("unchecked") @Override public PyObject __call__() { return new EnumerationIter(((Enumeration) self.getJavaProxy())); } }; - proxies.put(Enumeration.class, new PyBuiltinMethod[]{enumerationProxy}); + proxies.put(Enumeration.class, new PyBuiltinMethod[] {enumerationProxy}); proxies.put(List.class, JavaProxyList.getProxyMethods()); proxies.put(Map.class, JavaProxyMap.getProxyMethods()); proxies.put(Set.class, JavaProxySet.getProxyMethods()); @@ -1026,8 +1104,9 @@ return Collections.unmodifiableMap(postProxies); } - private class ClassComparator implements Comparator> { + private class ClassComparator implements Comparator> { + @Override public int compare(Class c1, Class c2) { if (c1.equals(c2)) { return 0; @@ -1050,7 +1129,7 @@ c = c.getSuperclass(); } while (c != null); - for (String name: nameStack) { + for (String name : nameStack) { namesBuilder.append(name); } @@ -1066,6 +1145,7 @@ this.classComparator = classComparator; } + @Override public int compare(Method m1, Method m2) { int result = m1.getName().compareTo(m2.getName()); @@ -1108,7 +1188,7 @@ return retVal; } if (conflicted != null) { - for (PyObject ob: conflicted) { + for (PyObject ob : conflicted) { if (ob != null) { retVal = visit.visit(ob, arg); if (retVal != 0) { @@ -1126,7 +1206,7 @@ return false; } if (conflicted != null) { - for (PyObject obj: conflicted) { + for (PyObject obj : conflicted) { if (obj == ob) { return true; } diff --git a/src/org/python/core/PyType.java b/src/org/python/core/PyType.java --- a/src/org/python/core/PyType.java +++ b/src/org/python/core/PyType.java @@ -7,11 +7,12 @@ import java.lang.ref.WeakReference; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; -import java.util.Map; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceArray; +import org.python.antlr.ast.cmpopType; import org.python.expose.ExposeAsSuperclass; import org.python.expose.ExposedDelete; import org.python.expose.ExposedGet; @@ -22,7 +23,6 @@ import org.python.expose.MethodType; import org.python.expose.TypeBuilder; import org.python.modules._weakref.WeakrefModule; -import org.python.antlr.ast.cmpopType; import org.python.util.Generic; import com.google.common.collect.MapMaker; @@ -40,8 +40,7 @@ public static final PyType TYPE = fromClass(PyType.class); /** - * The type's name. builtin types include their fully qualified name, e.g.: - * time.struct_time. + * The type's name. builtin types include their fully qualified name, e.g.: time.struct_time. */ protected String name; @@ -61,8 +60,8 @@ private long tp_flags; /** - * The Java Class instances of this type will be represented as, or null if it's - * determined by a base type. + * The Java Class instances of this type will be represented as, or null if it's determined by a + * base type. */ protected Class underlying_class; @@ -142,26 +141,25 @@ } /** Mapping of Java classes to their PyTypes. */ - private static ConcurrentMap, PyType> getClassToType() { - return StaticMaps.classToType; - } + private static ConcurrentMap, PyType> getClassToType() { + return StaticMaps.classToType; + } - /** Types that should not be garbage-collected (see {@link #fromClass(Class, boolean)} */ - private static Set getExposedTypes() { - return StaticMaps.exposedTypes; - } + /** Types that should not be garbage-collected (see {@link #fromClass(Class, boolean)} */ + private static Set getExposedTypes() { + return StaticMaps.exposedTypes; + } - /** Mapping of Java classes to their TypeBuilders. */ - private static ConcurrentMap, TypeBuilder> getClassToBuilder() { - return StaticMaps.classToBuilder; - } + /** Mapping of Java classes to their TypeBuilders. */ + private static ConcurrentMap, TypeBuilder> getClassToBuilder() { + return StaticMaps.classToBuilder; + } protected PyType(PyType subtype) { super(subtype); } - private PyType() { - } + private PyType() {} /** * Creates the PyType instance for type itself. The argument just exists to make the constructor @@ -173,7 +171,7 @@ @ExposedNew static final PyObject type___new__(PyNewWrapper new_, boolean init, PyType subtype, - PyObject[] args, String[] keywords) { + PyObject[] args, String[] keywords) { // Special case: type(x) should return x.getType() if (args.length == 1 && keywords.length == 0) { PyObject obj = args[0]; @@ -186,8 +184,10 @@ } return objType; } - // If that didn't trigger, we need 3 arguments. but ArgParser below may give a msg - // saying type() needs exactly 3. + /* + * If that didn't trigger, we need 3 arguments. but ArgParser below may give a msg saying + * type() needs exactly 3. + */ if (args.length + keywords.length != 3) { throw Py.TypeError("type() takes 1 or 3 arguments"); } @@ -215,7 +215,7 @@ } public static PyObject newType(PyNewWrapper new_, PyType metatype, String name, PyTuple bases, - PyObject dict) { + PyObject dict) { PyObject[] tmpBases = bases.getArray(); PyType winner = findMostDerivedMetatype(tmpBases, metatype); @@ -223,14 +223,15 @@ PyObject winnerNew = winner.lookup("__new__"); if (winnerNew != null && winnerNew != new_) { return invokeNew(winnerNew, winner, false, - new PyObject[] {new PyString(name), bases, dict}, Py.NoKeywords); + new PyObject[] {new PyString(name), bases, dict}, Py.NoKeywords); } metatype = winner; } - - // Use PyType as the metaclass for Python subclasses of Java classes rather than - // PyJavaType. Using PyJavaType as metaclass exposes the java.lang.Object methods - // on the type, which doesn't make sense for python subclasses. + /* + * Use PyType as the metaclass for Python subclasses of Java classes rather than PyJavaType. + * Using PyJavaType as metaclass exposes the java.lang.Object methods on the type, which + * doesn't make sense for python subclasses. + */ if (metatype == PyType.fromClass(Class.class)) { metatype = TYPE; } @@ -258,8 +259,8 @@ PyType base = type.base = best_base(type.bases); if (!base.isBaseType) { - throw Py.TypeError(String.format("type '%.100s' is not an acceptable base type", - base.name)); + throw Py.TypeError( + String.format("type '%.100s' is not an acceptable base type", base.name)); } type.createAllSlots(!(base.needs_userdict || defines_dict), !base.needs_weakref); @@ -267,17 +268,18 @@ type.invalidateMethodCache(); for (PyObject cur : type.bases) { - if (cur instanceof PyType) - ((PyType)cur).attachSubclass(type); + if (cur instanceof PyType) { + ((PyType) cur).attachSubclass(type); + } } return type; } /** - * Used internally by {@link #createAllSlots()}. - * Builds a naive pseudo mro used to collect all slot names relevant for this type. - * + * Used internally by {@link #createAllSlots()}. Builds a naive pseudo mro used to collect all + * slot names relevant for this type. + * * @param tp type to be investigated * @param dest list collecting all ancestors * @param slotsMap map linking each type to its slots @@ -296,7 +298,7 @@ slotsMap.put(tp, slots); } if (tp.bases.length > 1) { - for (PyObject base: tp.bases) { + for (PyObject base : tp.bases) { if (base == tp.base || !(base instanceof PyType) || ((PyType) base).numSlots == 0 || slotsMap.containsKey((PyType) base)) { continue; @@ -308,8 +310,8 @@ } /** - * Used internally by {@link #createAllSlots()}. - * Adds all names in {@code slots} to {@code dest}. + * Used internally by {@link #createAllSlots()}. Adds all names in {@code slots} to + * {@code dest}. * * @param slots names to be added as slots * @param dest set collecting all slots @@ -319,7 +321,7 @@ slots = new PyTuple(slots); } // Check for valid slot names and create them. - for (PyObject slot: slots.asIterable()) { + for (PyObject slot : slots.asIterable()) { String slotName = confirmIdentifier(slot); if (slotName.equals("__dict__") || slotName.equals("__weakref__")) { continue; @@ -335,23 +337,25 @@ * @param mayAddWeak whether a __weakref__ descriptor is allowed on this type */ private void createAllSlots(boolean mayAddDict, boolean mayAddWeak) { - List slottedAncestors = Generic.list(base.mro.length+(bases.length-1)*3+1); + List slottedAncestors = Generic.list(base.mro.length + (bases.length - 1) * 3 + 1); Map slotsMap = Generic.identityHashMap(slottedAncestors.size()); - /* Here we would need the mro to search for slots (also in secondary bases) properly, - but mro hasn't been set up yet. So we quickly (?) build a pseudo mro sufficient to - find all slots. */ + /* + * Here we would need the mro to search for slots (also in secondary bases) properly, but + * mro hasn't been set up yet. So we quickly (?) build a pseudo mro sufficient to find all + * slots. + */ int baseEnd = findSlottedAncestors(this, slottedAncestors, slotsMap); // baseEnd is the first position of an ancestor not equal to or ancestor of primary base int slots_tmp = 0; // used for various purpose, first to accumulate maximal slot count - for (PyType anc: slottedAncestors) { + for (PyType anc : slottedAncestors) { slots_tmp += anc.numSlots; } - /* In allSlots we collect slots of primary base first, then of this type, - then of secondary bases. - At any time we prevent it from containing __dict__ or __weakref__. */ - - // we know the required capacity, so the set likely won't be resized - Set allSlots = Generic.linkedHashSet(2*slots_tmp); + /* + * In allSlots we collect slots of primary base first, then of this type, then of secondary + * bases. At any time we prevent it from containing __dict__ or __weakref__. we know the + * required capacity, so the set likely won't be resized. + */ + Set allSlots = Generic.linkedHashSet(2 * slots_tmp); if (baseEnd > 0) { for (int i = 0; i < baseEnd; ++i) { insertSlots(slotsMap.get(slottedAncestors.get(i)), allSlots); @@ -363,8 +367,10 @@ boolean wantWeak = false; PyObject slots = dict.__finditem__("__slots__"); ownSlots = 0; // to keep track of slots defined by this type itself for isSolidBase - /* from now on, slots_tmp stores position where other ancestors than primary base - begin (points to this type if it defines own slots) */ + /* + * from now on, slots_tmp stores position where other ancestors than primary base begin + * (points to this type if it defines own slots) + */ if (slots == null) { wantDict = mayAddDict; wantWeak = mayAddWeak; @@ -379,10 +385,12 @@ if (slotName.equals("__dict__")) { if (!mayAddDict || wantDict) { - // CPython is stricter here, but this seems arbitrary. To reproduce CPython - // behavior + /* + * CPython is stricter here, but this seems arbitrary. To reproduce CPython + * behavior: + */ // if (base != PyObject.TYPE) { - // throw Py.TypeError("__dict__ slot disallowed: we already got one"); + // throw Py.TypeError("__dict__ slot disallowed: we already got one"); // } } else { wantDict = true; @@ -390,10 +398,12 @@ } } else if (slotName.equals("__weakref__")) { if ((!mayAddWeak || wantWeak) && base != PyObject.TYPE) { - // CPython is stricter here, but this seems arbitrary. To reproduce CPython - // behavior + /* + * CPython is stricter here, but this seems arbitrary. To reproduce CPython + * behavior: + */ // if (base != PyObject.TYPE) { - // throw Py.TypeError("__weakref__ slot disallowed: we already got one"); + // throw Py.TypeError("__weakref__ slot disallowed: we already got one"); // } } else { wantWeak = true; @@ -404,8 +414,7 @@ ++ownSlots; } } - if (bases.length > 1 && - ((mayAddDict && !wantDict) || (mayAddWeak && !wantWeak))) { + if (bases.length > 1 && ((mayAddDict && !wantDict) || (mayAddWeak && !wantWeak))) { // Secondary bases may provide weakrefs or dict for (PyObject base : bases) { if (base == this.base) { @@ -475,36 +484,37 @@ private void createDictSlot() { String doc = "dictionary for instance variables (if defined)"; dict.__setitem__("__dict__", new PyDataDescr(this, "__dict__", PyObject.class, doc) { - @Override - public boolean implementsDescrGet() { - return true; - } - @Override - public Object invokeGet(PyObject obj) { - return obj.getDict(); - } + @Override + public boolean implementsDescrGet() { + return true; + } - @Override - public boolean implementsDescrSet() { - return true; - } + @Override + public Object invokeGet(PyObject obj) { + return obj.getDict(); + } - @Override - public void invokeSet(PyObject obj, Object value) { - obj.setDict((PyObject)value); - } + @Override + public boolean implementsDescrSet() { + return true; + } - @Override - public boolean implementsDescrDelete() { - return true; - } + @Override + public void invokeSet(PyObject obj, Object value) { + obj.setDict((PyObject) value); + } - @Override - public void invokeDelete(PyObject obj) { - obj.delDict(); - } - }); + @Override + public boolean implementsDescrDelete() { + return true; + } + + @Override + public void invokeDelete(PyObject obj) { + obj.delDict(); + } + }); needs_userdict = true; } @@ -514,23 +524,23 @@ private void createWeakrefSlot() { String doc = "list of weak references to the object (if defined)"; dict.__setitem__("__weakref__", new PyDataDescr(this, "__weakref__", PyObject.class, doc) { - private static final String writeMsg = - "attribute '%s' of '%s' objects is not writable"; - private void notWritable(PyObject obj) { - throw Py.AttributeError(String.format(writeMsg, "__weakref__", - obj.getType().fastGetName())); - } + private static final String writeMsg = "attribute '%s' of '%s' objects is not writable"; - @Override - public boolean implementsDescrGet() { - return true; - } + private void notWritable(PyObject obj) { + throw Py.AttributeError( + String.format(writeMsg, "__weakref__", obj.getType().fastGetName())); + } - @Override - public Object invokeGet(PyObject obj) { - PyList weakrefs = WeakrefModule.getweakrefs(obj); - switch (weakrefs.size()) { + @Override + public boolean implementsDescrGet() { + return true; + } + + @Override + public Object invokeGet(PyObject obj) { + PyList weakrefs = WeakrefModule.getweakrefs(obj); + switch (weakrefs.size()) { case 0: return Py.None; case 1: @@ -538,30 +548,30 @@ default: return weakrefs; - } } + } - @Override - public boolean implementsDescrSet() { - return true; - } + @Override + public boolean implementsDescrSet() { + return true; + } - @Override - public void invokeSet(PyObject obj, Object value) { - // XXX: Maybe have PyDataDescr do notWritable() for us - notWritable(obj); - } + @Override + public void invokeSet(PyObject obj, Object value) { + // XXX: Maybe have PyDataDescr do notWritable() for us + notWritable(obj); + } - @Override - public boolean implementsDescrDelete() { - return true; - } + @Override + public boolean implementsDescrDelete() { + return true; + } - @Override - public void invokeDelete(PyObject obj) { - notWritable(obj); - } - }); + @Override + public void invokeDelete(PyObject obj) { + notWritable(obj); + } + }); needs_weakref = true; } @@ -610,8 +620,7 @@ } /** - * Ensure dict contains a __module__, retrieving it from the current frame if it - * doesn't exist. + * Ensure dict contains a __module__, retrieving it from the current frame if it doesn't exist. * * @param dict a PyObject mapping */ @@ -630,10 +639,10 @@ } private static PyObject invokeNew(PyObject new_, PyType type, boolean init, PyObject[] args, - String[] keywords) { + String[] keywords) { PyObject obj; if (new_ instanceof PyNewWrapper) { - obj = ((PyNewWrapper)new_).new_impl(init, type, args, keywords); + obj = ((PyNewWrapper) new_).new_impl(init, type, args, keywords); } else { int n = args.length; PyObject[] typePrepended = new PyObject[n + 1]; @@ -665,24 +674,27 @@ computeLinearMro(baseClass); } if (BootstrapTypesSingleton.getInstance().contains(underlying_class)) { - // init will be called again from addBuilder which also removes underlying_class from - // BOOTSTRAP_TYPES + /* + * init will be called again from addBuilder which also removes underlying_class from + * BOOTSTRAP_TYPES. + */ return; } TypeBuilder builder = getClassToBuilder().get(underlying_class); name = builder.getName(); dict = builder.getDict(this); String doc = builder.getDoc(); - // XXX: Can't create a __doc__ str until the PyBaseString/PyString types are - // created + // XXX: Can't create a __doc__ str until the PyBaseString/PyString types are created if (dict.__finditem__("__doc__") == null && forClass != PyBaseString.class - && forClass != PyString.class) { + && forClass != PyString.class) { PyObject docObj; if (doc != null) { docObj = new PyString(doc); } else { - // XXX: Hack: Py.None may be null during bootstrapping. Most types - // encountered then should have docstrings anyway + /* + * XXX: Hack: Py.None may be null during bootstrapping. Most types encountered then + * should have docstrings anyway. + */ docObj = Py.None == null ? new PyString() : Py.None; } dict.__setitem__("__doc__", docObj); @@ -705,7 +717,6 @@ bases = new PyObject[] {base}; } - /** * Determine if this type is a descriptor, and if so what kind. */ @@ -730,11 +741,10 @@ */ public final boolean needsFinalizer() { /* - * It might be sluggish to assume that if a finalizer was needed - * once, this would never change. However since an expensive - * FinalizeTrigger was created anyway, it won't hurt to keep it. - * Whether there actually is a __del__ in the dict, will be checked - * again when the finalizer runs. + * It might be sluggish to assume that if a finalizer was needed once, this would never + * change. However since an expensive FinalizeTrigger was created anyway, it won't hurt to + * keep it. Whether there actually is a __del__ in the dict, will be checked again when the + * finalizer runs. */ if (needs_finalizer) { return true; @@ -750,9 +760,9 @@ */ public void compatibleForAssignment(PyType other, String attribute) { if (!getLayout().equals(other.getLayout()) || needs_userdict != other.needs_userdict - || needs_finalizer != other.needs_finalizer) { + || needs_finalizer != other.needs_finalizer) { throw Py.TypeError(String.format("%s assignment: '%s' object layout differs from '%s'", - attribute, other.fastGetName(), fastGetName())); + attribute, other.fastGetName(), fastGetName())); } } @@ -770,8 +780,7 @@ } /** - * Get the most parent Java proxy Class from bases, tallying any encountered Java - * interfaces. + * Get the most parent Java proxy Class from bases, tallying any encountered Java interfaces. * * @param bases array of base Jython classes * @param interfaces List for collecting interfaces to @@ -785,7 +794,7 @@ if (!(base instanceof PyType)) { continue; } - Class proxy = ((PyType)base).getProxyType(); + Class proxy = ((PyType) base).getProxyType(); if (proxy == null) { continue; } @@ -820,9 +829,9 @@ if (module != null) { proxyName = module.toString() + "$" + proxyName; } - Class proxyClass = MakeProxies.makeProxy(baseProxyClass, interfaces, name, proxyName, - dict); - JyAttribute.setAttr(this, JyAttribute.JAVA_PROXY_ATTR, proxyClass); + Class proxyClass = + MakeProxies.makeProxy(baseProxyClass, interfaces, name, proxyName, dict); + JyAttribute.setAttr(this, JyAttribute.JAVA_PROXY_ATTR, proxyClass); PyType proxyType = PyType.fromClass(proxyClass, false); List cleanedBases = Generic.list(); @@ -832,19 +841,23 @@ cleanedBases.add(base); continue; } - Class proxy = ((PyType)base).getProxyType(); + Class proxy = ((PyType) base).getProxyType(); if (proxy == null) { // non-proxy types go straight into our lookup cleanedBases.add(base); } else { if (!(base instanceof PyJavaType)) { - // python subclasses of proxy types need to be added as a base so their - // version of methods will show up + /* + * python subclasses of proxy types need to be added as a base so their version + * of methods will show up. + */ cleanedBases.add(base); } else if (!addedProxyType) { - // Only add a single Java type, since everything's going to go through the - // proxy type + /* + * Only add a single Java type, since everything's going to go through the proxy + * type. + */ cleanedBases.add(proxyType); addedProxyType = true; } @@ -859,12 +872,14 @@ return null; } - // If there is a __cmp__ method defined, let it be called instead - // of our dumb function designed merely to warn. See CPython bug #7491. - if (__findattr__("__cmp__") != null || ((PyType)other).__findattr__("__cmp__") != null) { + /* + * If there is a __cmp__ method defined, let it be called instead of our dumb function + * designed merely to warn. See CPython bug #7491. + */ + if (__findattr__("__cmp__") != null || ((PyType) other).__findattr__("__cmp__") != null) { return null; } - + // Py3K warning if comparison isn't == or != if (Options.py3k_warning && op != cmpopType.Eq && op != cmpopType.NotEq) { Py.warnPy3k("type inequality comparisons not supported in 3.x"); @@ -875,16 +890,23 @@ int hash1 = object___hash__(); int hash2 = other.object___hash__(); switch (op) { - case Lt: return hash1 < hash2 ? Py.True : Py.False; - case LtE: return hash1 <= hash2 ? Py.True : Py.False; - case Eq: return hash1 == hash2 ? Py.True : Py.False; - case NotEq: return hash1 != hash2 ? Py.True : Py.False; - case Gt: return hash1 > hash2 ? Py.True : Py.False; - case GtE: return hash1 >= hash2 ? Py.True : Py.False; - default: return null; + case Lt: + return hash1 < hash2 ? Py.True : Py.False; + case LtE: + return hash1 <= hash2 ? Py.True : Py.False; + case Eq: + return hash1 == hash2 ? Py.True : Py.False; + case NotEq: + return hash1 != hash2 ? Py.True : Py.False; + case Gt: + return hash1 > hash2 ? Py.True : Py.False; + case GtE: + return hash1 >= hash2 ? Py.True : Py.False; + default: + return null; } } - + @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.type___eq___doc) public PyObject type___eq__(PyObject other) { return richCompare(other, cmpopType.Eq); @@ -914,11 +936,12 @@ public PyObject type___gt__(PyObject other) { return richCompare(other, cmpopType.Gt); } - + @ExposedGet(name = "__base__") public PyObject getBase() { - if (base == null) + if (base == null) { return Py.None; + } return base; } @@ -937,19 +960,19 @@ if (!(newBasesTuple instanceof PyTuple)) { throw Py.TypeError("bases must be a tuple"); } - PyObject[] newBases = ((PyTuple)newBasesTuple).getArray(); + PyObject[] newBases = ((PyTuple) newBasesTuple).getArray(); if (newBases.length == 0) { - throw Py.TypeError("can only assign non-empty tuple to __bases__, not " - + newBasesTuple); + throw Py.TypeError( + "can only assign non-empty tuple to __bases__, not " + newBasesTuple); } for (int i = 0; i < newBases.length; i++) { if (!(newBases[i] instanceof PyType)) { if (!(newBases[i] instanceof PyClass)) { throw Py.TypeError(name + ".__bases__ must be a tuple of old- or new-style " - + "classes, not " + newBases[i]); + + "classes, not " + newBases[i]); } } else { - if (((PyType)newBases[i]).isSubType(this)) { + if (((PyType) newBases[i]).isSubType(this)) { throw Py.TypeError("a __bases__ item causes an inheritance cycle"); } } @@ -967,18 +990,18 @@ mro_subclasses(savedSubMros); for (PyObject saved : savedBases) { if (saved instanceof PyType) { - ((PyType)saved).detachSubclass(this); + ((PyType) saved).detachSubclass(this); } } for (PyObject newb : newBases) { if (newb instanceof PyType) { - ((PyType)newb).attachSubclass(this); + ((PyType) newb).attachSubclass(this); } } } catch (PyException t) { for (Iterator it = savedSubMros.iterator(); it.hasNext();) { - PyType subtype = (PyType)it.next(); - PyObject[] subtypeSavedMro = (PyObject[])it.next(); + PyType subtype = (PyType) it.next(); + PyObject[] subtypeSavedMro = (PyObject[]) it.next(); subtype.mro = subtypeSavedMro; } bases = savedBases; @@ -1015,12 +1038,13 @@ } if (!(cls instanceof PyType)) { throw Py.TypeError(String.format("mro() returned a non-class ('%.500s')", - cls.getType().fastGetName())); + cls.getType().fastGetName())); } - PyType t = (PyType)cls; + PyType t = (PyType) cls; if (!solid.isSubType(solid_base(t))) { - throw Py.TypeError(String.format("mro() returned base with unsuitable layout " - + "('%.500s')", t.fastGetName())); + throw Py.TypeError(String.format( + "mro() returned base with unsuitable layout " + "('%.500s')", + t.fastGetName())); } } mro = result; @@ -1075,8 +1099,9 @@ cleanup_subclasses(); for (WeakReference ref : subclasses) { PyType subtype = ref.get(); - if (subtype == null) + if (subtype == null) { continue; + } result.append(subtype); } return result; @@ -1084,18 +1109,19 @@ @ExposedMethod(doc = BuiltinDocs.type___subclasscheck___doc) public synchronized final boolean type___subclasscheck__(PyObject inst) { - /* We cannot directly call Py.isSubClass(inst, this), because that - * would yield endless recursion under some circumstances (e.g. in - * test_collections). + /* + * We cannot directly call Py.isSubClass(inst, this), because that would yield endless + * recursion under some circumstances (e.g. in test_collections). */ return Py.recursiveIsSubClass(inst, this); } @ExposedMethod(doc = BuiltinDocs.type___instancecheck___doc) public synchronized final boolean type___instancecheck__(PyObject inst) { - /* We cannot directly call Py.isInstance(inst, this), because that - * would yield endless recursion. So we inline the essential parts - * from there, excluding checker-delegation and PyTuple special case. + /* + * We cannot directly call Py.isInstance(inst, this), because that would yield endless + * recursion. So we inline the essential parts from there, excluding checker-delegation and + * PyTuple special case. */ if (inst.getType() == this) { return true; @@ -1148,7 +1174,7 @@ } PyObject[] bases = classic_cl.__bases__.getArray(); for (PyObject base : bases) { - fill_classic_mro(acc,(PyClass)base); + fill_classic_mro(acc, (PyClass) base); } } @@ -1163,7 +1189,7 @@ if (o == null) { return new PyList(computeMro()); } - return new PyList(((PyType)o).computeMro()); + return new PyList(((PyType) o).computeMro()); } PyObject[] computeMro() { @@ -1172,8 +1198,8 @@ for (int j = i + 1; j < bases.length; j++) { if (bases[j] == cur) { PyObject name = cur.__findattr__("__name__"); - throw Py.TypeError("duplicate base class " + - (name == null ? "?" : name.toString())); + throw Py.TypeError( + "duplicate base class " + (name == null ? "?" : name.toString())); } } } @@ -1182,9 +1208,9 @@ for (int i = 0; i < bases.length; i++) { toMerge[i] = new MROMergeState(); if (bases[i] instanceof PyType) { - toMerge[i].mro = ((PyType)bases[i]).mro; + toMerge[i].mro = ((PyType) bases[i]).mro; } else if (bases[i] instanceof PyClass) { - toMerge[i].mro = classic_mro((PyClass)bases[i]); + toMerge[i].mro = classic_mro((PyClass) bases[i]); } } toMerge[bases.length] = new MROMergeState(); @@ -1197,8 +1223,9 @@ PyObject[] computeMro(MROMergeState[] toMerge, List mro) { boolean addedProxy = false; - PyType proxyAsType = !JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR) ? - null : PyType.fromClass(((Class)JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR)), false); + PyType proxyAsType = + !JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR) ? null : PyType.fromClass( + ((Class) JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR)), false); scan : for (int i = 0; i < toMerge.length; i++) { if (toMerge[i].isMerged()) { continue scan; @@ -1212,15 +1239,17 @@ } if (!addedProxy && !(this instanceof PyJavaType) && candidate instanceof PyJavaType && JyAttribute.hasAttr(candidate, JyAttribute.JAVA_PROXY_ATTR) - && PyProxy.class.isAssignableFrom( - ((Class)JyAttribute.getAttr(candidate, JyAttribute.JAVA_PROXY_ATTR))) - && JyAttribute.getAttr(candidate, JyAttribute.JAVA_PROXY_ATTR) != - JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR)) { - // If this is a subclass of a Python class that subclasses a Java class, slip the - // proxy for this class in before the proxy class in the superclass' mro. - // This exposes the methods from the proxy generated for this class in addition to - // those generated for the superclass while allowing methods from the superclass to - // remain visible from the proxies. + && PyProxy.class.isAssignableFrom(((Class) JyAttribute.getAttr(candidate, + JyAttribute.JAVA_PROXY_ATTR))) + && JyAttribute.getAttr(candidate, JyAttribute.JAVA_PROXY_ATTR) != JyAttribute + .getAttr(this, JyAttribute.JAVA_PROXY_ATTR)) { + /* + * If this is a subclass of a Python class that subclasses a Java class, slip the + * proxy for this class in before the proxy class in the superclass' mro. This + * exposes the methods from the proxy generated for this class in addition to those + * generated for the superclass while allowing methods from the superclass to remain + * visible from the proxies. + */ mro.add(proxyAsType); addedProxy = true; } @@ -1245,11 +1274,11 @@ * finishing filling in mro. */ void handleMroError(MROMergeState[] toMerge, List mro) { - StringBuilder msg = new StringBuilder("Cannot create a consistent method resolution\n" - + "order (MRO) for bases "); + StringBuilder msg = new StringBuilder( + "Cannot create a consistent method resolution\n" + "order (MRO) for bases "); Set set = Generic.set(); for (MROMergeState mergee : toMerge) { - if(!mergee.isMerged()) { + if (!mergee.isMerged()) { set.add(mergee.mro[0]); } } @@ -1261,14 +1290,14 @@ } else { msg.append(", "); } - msg.append(name == null ? "?" : name.toString() + new PyList(((PyType)unmerged).bases)); + msg.append( + name == null ? "?" : name.toString() + new PyList(((PyType) unmerged).bases)); } throw Py.TypeError(msg.toString()); } /** - * Finds the parent of type with an underlying_class or with slots sans a __dict__ - * slot. + * Finds the parent of type with an underlying_class or with slots sans a __dict__ slot. */ private static PyType solid_base(PyType type) { do { @@ -1301,15 +1330,15 @@ if (!(base instanceof PyType)) { throw Py.TypeError("bases must be types"); } - candidate = solid_base((PyType)base); + candidate = solid_base((PyType) base); if (winner == null) { winner = candidate; - best = (PyType)base; + best = (PyType) base; } else if (winner.isSubType(candidate)) { ; } else if (candidate.isSubType(winner)) { winner = candidate; - best = (PyType)base; + best = (PyType) base; } else { throw Py.TypeError("multiple bases have instance lay-out conflict"); } @@ -1325,17 +1354,16 @@ } /** - * Finds the most derived subtype of initialMetatype in the types - * of bases, or initialMetatype if it is already the most derived. + * Finds the most derived subtype of initialMetatype in the types of bases, or initialMetatype + * if it is already the most derived. * - * @raises Py.TypeError if the all the metaclasses don't descend - * from the same base - * @raises Py.TypeError if one of the bases is a PyJavaClass or a - * PyClass with no proxyClass + * @raises Py.TypeError if the all the metaclasses don't descend from the same base + * @raises Py.TypeError if one of the bases is a PyJavaClass or a PyClass with no proxyClass */ private static PyType findMostDerivedMetatype(PyObject[] bases_list, PyType initialMetatype) { PyType winner = initialMetatype; - if (isJavaRootClass(winner)) { // consider this root class to be equivalent to type + if (isJavaRootClass(winner)) { + // consider this root class to be equivalent to type winner = PyType.TYPE; } @@ -1356,7 +1384,7 @@ continue; } throw Py.TypeError("metaclass conflict: the metaclass of a derived class must be a " - + "(non-strict) subclass of the metaclasses of all its bases"); + + "(non-strict) subclass of the metaclasses of all its bases"); } return winner; } @@ -1393,8 +1421,8 @@ } /** - * Attribute lookup for name directly through mro objects' dicts. This isn't cached, - * and should generally only be used during the bootstrapping of a type. + * Attribute lookup for name directly through mro objects' dicts. This isn't cached, and should + * generally only be used during the bootstrapping of a type. * * @param name attribute name (must be interned) * @return found object or null @@ -1417,8 +1445,8 @@ } /** - * Attribute lookup for name through mro objects' dicts. This isn't cached, and should - * generally only be used during the bootstrapping of a type. + * Attribute lookup for name through mro objects' dicts. This isn't cached, and should generally + * only be used during the bootstrapping of a type. * * Returns where in the mro the attribute was found at where[0]. * @@ -1454,21 +1482,23 @@ } int i; for (i = 0; i < mro.length; i++) { - if (mro[i] == ref) + if (mro[i] == ref) { break; + } } i++; for (; i < mro.length; i++) { if (mro[i] instanceof PyJavaType) { - // The MRO contains this proxy for classes extending a Java class and/or - // interfaces, but the proxy points back to this starting Python class. - // So break out of this infinite loop by ignoring this entry for super purposes. - // The use of super__ parallels the workaround seen in PyReflectedFunction - // Fixes http://bugs.jython.org/issue1540 - // Also ignore this if we're doing super during __init__ as we want it to behave - // Fixes http://bugs.jython.org/issue2375 - if(name != "__init__" && !name.startsWith("super__")) { - lookupName = "super__" + name; + /* + * The MRO contains this proxy for classes extending a Java class and/or interfaces, + * but the proxy points back to this starting Python class. So break out of this + * infinite loop by ignoring this entry for super purposes. The use of super__ + * parallels the workaround seen in PyReflectedFunction Fixes + * http://bugs.jython.org/issue1540 Also ignore this if we're doing super during + * __init__ as we want it to behave Fixes http://bugs.jython.org/issue2375 + */ + if (name != "__init__" && !name.startsWith("super__")) { + lookupName = "super__" + name; } else { lookupName = name; } @@ -1490,11 +1520,14 @@ getClassToBuilder().put(forClass, builder); if (getClassToType().containsKey(forClass)) { if (!BootstrapTypesSingleton.getInstance().remove(forClass)) { - Py.writeWarning("init", "Bootstrapping class not in BootstrapTypesSingleton.getInstance()[class=" - + forClass + "]"); + Py.writeWarning("init", + "Bootstrapping class not in BootstrapTypesSingleton.getInstance()[class=" + + forClass + "]"); } - // The types in BootstrapTypesSingleton.getClassToType() are initialized before their builders are assigned, - // so do the work of addFromClass & fillFromClass after the fact + /* + * The types in BootstrapTypesSingleton.getClassToType() are initialized before their + * builders are assigned, so do the work of addFromClass & fillFromClass after the fact. + */ fromClass(builder.getTypeClass()).init(builder.getTypeClass(), null); } } @@ -1511,41 +1544,48 @@ static boolean hasBuilder(Class c) { return getClassToBuilder().containsKey(c); } - + private static TypeBuilder getBuilder(Class c) { if (c.isPrimitive() || !PyObject.class.isAssignableFrom(c)) { - // If this isn't a PyObject, don't bother forcing it to be initialized to load its - // builder + /* + * If this isn't a PyObject, don't bother forcing it to be initialized to load its + * builder + */ return null; + } else { + /* + * This is a PyObject, call forName to force static initialization on the class so if it + * has a builder, it'll be filled in. + */ + SecurityException exc = null; + try { + Class.forName(c.getName(), true, c.getClassLoader()); + } catch (ClassNotFoundException e) { + // Well, this is certainly surprising. + throw new RuntimeException( + "Got ClassNotFound calling Class.forName on an already " + " found class.", + e); + } catch (ExceptionInInitializerError e) { + throw Py.JavaError(e); + } catch (SecurityException e) { + exc = e; + } + TypeBuilder builder = getClassToBuilder().get(c); + if (builder == null && exc != null) { + Py.writeComment("type", + "Unable to initialize " + c.getName() + ", a PyObject subclass, due to a " + + "security exception, and no type builder could be found for it. " + + "If it's an exposed type, it may not work properly. " + + "Security exception: " + exc.getMessage()); + } + return builder; } - - // This is a PyObject, call forName to force static initialization on the class so if it has - // a builder, it'll be filled in - SecurityException exc = null; - try { - Class.forName(c.getName(), true, c.getClassLoader()); - } catch (ClassNotFoundException e) { - // Well, this is certainly surprising. - throw new RuntimeException("Got ClassNotFound calling Class.forName on an already " - + " found class.", e); - } catch (ExceptionInInitializerError e) { - throw Py.JavaError(e); - } catch (SecurityException e) { - exc = e; - } - TypeBuilder builder = getClassToBuilder().get(c); - if (builder == null && exc != null) { - Py.writeComment("type", - "Unable to initialize " + c.getName() + ", a PyObject subclass, due to a " + - "security exception, and no type builder could be found for it. If it's an " + - "exposed type, it may not work properly. Security exception: " + - exc.getMessage()); - } - return builder; } private synchronized static PyType createType(Class c, Set needsInners) { - // System.out.println("createType c=" + c + ", needsInners=" + needsInners + ", BootstrapTypesSingleton.getInstance()=" + BootstrapTypesSingleton.getInstance()); + // System.out.println("createType c=" + c + ", needsInners=" + needsInners + // + ", BootstrapTypesSingleton.getInstance()=" + // + BootstrapTypesSingleton.getInstance()); PyType newtype; if (c == PyType.class) { newtype = new PyType(false); @@ -1602,9 +1642,11 @@ if (type != null) { return type; } - // We haven't seen this class before, so its type needs to be created. If it's being - // exposed as a Java class, defer processing its inner types until it's completely - // created in case the inner class references a class that references this class. + /* + * We haven't seen this class before, so its type needs to be created. If it's being exposed + * as a Java class, defer processing its inner types until it's completely created in case + * the inner class references a class that references this class. + */ Set needsInners = Generic.set(); PyType result = addFromClass(c, needsInners); for (PyJavaType javaType : needsInners) { @@ -1613,23 +1655,28 @@ continue; } for (Class inner : forClass.getClasses()) { - // Only add the class if there isn't something else with that name and it came from this - // class - if (inner.getDeclaringClass() == forClass && - javaType.dict.__finditem__(inner.getSimpleName()) == null) { - // If this class is currently being loaded, any exposed types it contains won't have - // set their builder in PyType yet, so add them to BOOTSTRAP_TYPES so they're - // created as PyType instead of PyJavaType + /* + * Only add the class if there isn't something else with that name and it came from + * this class + */ + if (inner.getDeclaringClass() == forClass + && javaType.dict.__finditem__(inner.getSimpleName()) == null) { + /* + * If this class is currently being loaded, any exposed types it contains won't + * have set their builder in PyType yet, so add them to BOOTSTRAP_TYPES so + * they're created as PyType instead of PyJavaType + */ if (inner.getAnnotation(ExposedType.class) != null || ExposeAsSuperclass.class.isAssignableFrom(inner)) { BootstrapTypesSingleton.getInstance().add(inner); } - javaType.dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner, hardRef)); + javaType.dict.__setitem__(inner.getSimpleName(), + PyType.fromClass(inner, hardRef)); } } } if (hardRef && result != null) { - getExposedTypes().add(result) ; + getExposedTypes().add(result); } return result; @@ -1653,6 +1700,7 @@ return ret; } + @Override public PyObject __findattr_ex__(String name) { return type___findattr_ex__(name); } @@ -1667,8 +1715,9 @@ get = metaattr.implementsDescrGet(); if (useMetatypeFirst(metaattr) && get && metaattr.isDataDescr()) { PyObject res = metaattr.__get__(this, metatype); - if (res != null) + if (res != null) { return res; + } } } @@ -1705,8 +1754,9 @@ type___setattr__(asName(name), value); } + @Override public void __setattr__(String name, PyObject value) { - type___setattr__(name, value); + type___setattr__(name, value); } /** @@ -1727,8 +1777,8 @@ void type___setattr__(String name, PyObject value) { if (builtin) { - throw Py.TypeError(String.format("can't set attributes of built-in/extension type " - + "'%s'", this.name)); + throw Py.TypeError(String.format( + "can't set attributes of built-in/extension type " + "'%s'", this.name)); } super.__setattr__(name, value); postSetattr(name); @@ -1739,6 +1789,8 @@ if (name == "__get__") { if (!hasGet && lookup("__get__") != null) { traverse_hierarchy(false, new OnType() { + + @Override public boolean onType(PyType type) { boolean old = type.hasGet; type.hasGet = true; @@ -1749,6 +1801,8 @@ } else if (name == "__set__") { if (!hasSet && lookup("__set__") != null) { traverse_hierarchy(false, new OnType() { + + @Override public boolean onType(PyType type) { boolean old = type.hasSet; type.hasSet = true; @@ -1759,6 +1813,8 @@ } else if (name == "__delete__") { if (!hasDelete && lookup("__delete__") != null) { traverse_hierarchy(false, new OnType() { + + @Override public boolean onType(PyType type) { boolean old = type.hasDelete; type.hasDelete = true; @@ -1768,13 +1824,16 @@ } } else if (name == "__getattribute__") { traverse_hierarchy(false, new OnType() { - public boolean onType(PyType type) { - return (type.usesObjectGetattribute = false); - } - }); + + @Override + public boolean onType(PyType type) { + return (type.usesObjectGetattribute = false); + } + }); } } + @Override public void __delattr__(String name) { type___delattr__(name); } @@ -1784,13 +1843,12 @@ type___delattr__(asName(name)); } - protected void checkDelattr() { - } + protected void checkDelattr() {} void type___delattr__(String name) { if (builtin) { - throw Py.TypeError(String.format("can't set attributes of built-in/extension type " - + "'%s'", this.name)); + throw Py.TypeError(String.format( + "can't set attributes of built-in/extension type " + "'%s'", this.name)); } super.__delattr__(name); postDelattr(name); @@ -1801,6 +1859,8 @@ if (name == "__get__") { if (hasGet && lookup("__get__") == null) { traverse_hierarchy(false, new OnType() { + + @Override public boolean onType(PyType type) { boolean absent = type.getDict().__finditem__("__get__") == null; if (absent) { @@ -1814,6 +1874,8 @@ } else if (name == "__set__") { if (hasSet && lookup("__set__") == null) { traverse_hierarchy(false, new OnType() { + + @Override public boolean onType(PyType type) { boolean absent = type.getDict().__finditem__("__set__") == null; if (absent) { @@ -1827,6 +1889,8 @@ } else if (name == "__delete__") { if (hasDelete && lookup("__delete__") == null) { traverse_hierarchy(false, new OnType() { + + @Override public boolean onType(PyType type) { boolean absent = type.getDict().__finditem__("__delete__") == null; if (absent) { @@ -1839,26 +1903,31 @@ } } else if (name == "__getattribute__") { traverse_hierarchy(false, new OnType() { - public boolean onType(PyType type) { - return (type.usesObjectGetattribute = false); - } - }); + + @Override + public boolean onType(PyType type) { + return (type.usesObjectGetattribute = false); + } + }); } } /** - * Invalidate this type's MethodCache entries. *Must* be called after any modification - * to __dict__ (or anything else affecting attribute lookups). + * Invalidate this type's MethodCache entries. *Must* be called after any modification to + * __dict__ (or anything else affecting attribute lookups). */ protected void invalidateMethodCache() { traverse_hierarchy(false, new OnType() { - public boolean onType(PyType type) { - type.versionTag = new Object(); - return false; - } - }); + + @Override + public boolean onType(PyType type) { + type.versionTag = new Object(); + return false; + } + }); } + @Override public PyObject __call__(PyObject[] args, String[] keywords) { return type___call__(args, keywords); } @@ -1871,16 +1940,19 @@ } PyObject obj = invokeNew(new_, this, true, args, keywords); - // When the call was type(something) or the returned object is not an instance of - // type, it won't be initialized + /* + * When the call was type(something) or the returned object is not an instance of type, it + * won't be initialized + */ if ((this == TYPE && args.length == 1 && keywords.length == 0) - || !obj.getType().isSubType(this)) { + || !obj.getType().isSubType(this)) { return obj; } obj.dispatch__init__(args, keywords); return obj; } + @Override protected void __rawdir__(PyDictionary accum) { mergeClassDict(accum, this); } @@ -1910,10 +1982,10 @@ // guarded by __setattr__ to prevent modification of builtins if (!(name instanceof PyString)) { throw Py.TypeError(String.format("can only assign string to %s.__name__, not '%s'", - this.name, name.getType().fastGetName())); + this.name, name.getType().fastGetName())); } String nameStr = name.toString(); - if (nameStr.indexOf((char)0) > -1) { + if (nameStr.indexOf((char) 0) > -1) { throw Py.ValueError("__name__ must not contain null bytes"); } setName(nameStr); @@ -1944,13 +2016,16 @@ return new PyDictProxy(dict); } + @Override @ExposedSet(name = "__dict__") public void setDict(PyObject newDict) { // Analogous to CPython's descrobject:getset_set - throw Py.AttributeError(String.format("attribute '__dict__' of '%s' objects is not " - + "writable", getType().fastGetName())); + throw Py.AttributeError( + String.format("attribute '__dict__' of '%s' objects is not " + "writable", + getType().fastGetName())); } + @Override @ExposedDelete(name = "__dict__") public void delDict() { setDict(null); @@ -1976,9 +2051,10 @@ this.usesObjectGetattribute = usesObjectGetattribute; } + @Override public Object __tojava__(Class c) { - if (underlying_class != null && (c == Object.class || c == Class.class || - c == Serializable.class)) { + if (underlying_class != null + && (c == Object.class || c == Class.class || c == Serializable.class)) { return underlying_class; } return super.__tojava__(c); @@ -2012,15 +2088,16 @@ @ExposedSet(name = "__abstractmethods__") public void setAbstractmethods(PyObject value) { - // __abstractmethods__ should only be set once on a type, in abc.ABCMeta.__new__, - // so this function doesn't do anything special to update subclasses + /* + * __abstractmethods__ should only be set once on a type, in abc.ABCMeta.__new__, so this + * function doesn't do anything special to update subclasses + */ dict.__setitem__("__abstractmethods__", value); postSetattr("__abstractmethods__"); - tp_flags = value.__nonzero__() - ? tp_flags | Py.TPFLAGS_IS_ABSTRACT + tp_flags = value.__nonzero__() ? tp_flags | Py.TPFLAGS_IS_ABSTRACT : tp_flags & ~Py.TPFLAGS_IS_ABSTRACT; } - + public int getNumSlots() { return numSlots; } @@ -2040,35 +2117,39 @@ return String.format("<%s '%s'>", kind, getName()); } + @Override public String toString() { return type_toString(); } /** - * Raises AttributeError on type objects. The message differs from - * PyObject#noAttributeError, to mimic CPython behaviour. + * Raises AttributeError on type objects. The message differs from PyObject#noAttributeError, to + * mimic CPython behaviour. */ + @Override public void noAttributeError(String name) { throw Py.AttributeError(String.format("type object '%.50s' has no attribute '%.400s'", - fastGetName(), name)); + fastGetName(), name)); } - //XXX: consider pulling this out into a generally accessible place - // I bet this is duplicated more or less in other places. + /* + * XXX: consider pulling this out into a generally accessible place. I bet this is duplicated + * more or less in other places. + */ private static String confirmIdentifier(PyObject obj) { String identifier; if (!(obj instanceof PyString)) { throw Py.TypeError(String.format("__slots__ items must be strings, not '%.200s'", - obj.getType().fastGetName())); + obj.getType().fastGetName())); } else if (obj instanceof PyUnicode) { - identifier = ((PyUnicode)obj).encode(); + identifier = ((PyUnicode) obj).encode(); } else { identifier = obj.toString(); } String msg = "__slots__ must be identifiers"; if (identifier.length() == 0 - || (!Character.isLetter(identifier.charAt(0)) && identifier.charAt(0) != '_')) { + || (!Character.isLetter(identifier.charAt(0)) && identifier.charAt(0) != '_')) { throw Py.TypeError(msg); } for (char c : identifier.toCharArray()) { @@ -2079,11 +2160,13 @@ return identifier; } - //XXX: copied from CodeCompiler.java and changed variable names. - // Maybe this should go someplace for all classes to use. + /* + * XXX: copied from CodeCompiler.java and changed variable names. Maybe this should go someplace + * for all classes to use. + */ private static String mangleName(String classname, String methodname) { if (classname != null && methodname.startsWith("__") && !methodname.endsWith("__")) { - //remove leading '_' from classname + // remove leading '_' from classname int i = 0; while (classname.charAt(i) == '_') { i++; @@ -2112,8 +2195,10 @@ private String name; TypeResolver(Class underlying_class, String module, String name) { - // Don't store the underlying_class for PyProxies as the proxy type needs to fill in - // based on the class, not be the class + /* + * Don't store the underlying_class for PyProxies as the proxy type needs to fill in + * based on the class, not be the class + */ if (underlying_class != null && !PyProxy.class.isAssignableFrom(underlying_class)) { this.underlying_class = underlying_class; } @@ -2199,7 +2284,7 @@ */ static class MethodCache { - /** Global mro cache. See {@link PyType#lookup_where(String, PyObject[])}.*/ + /** Global mro cache. See {@link PyType#lookup_where(String, PyObject[])}. */ private static final MethodCache methodCache = new MethodCache(); /** The fixed size cache. */ @@ -2235,12 +2320,14 @@ } PyObject value = type.lookup_where_mro(name, where); if (isCacheableName(name)) { - // CAS isn't totally necessary here but is possibly more correct. Cache by - // the original version before the lookup, if it's changed since then - // we'll cache a bad entry. Bad entries and CAS failures aren't a concern - // as subsequent lookups will sort themselves out - table.compareAndSet(index, entry, new MethodCacheEntry(versionTag, name, where[0], - value)); + /* + * CAS isn't totally necessary here but is possibly more correct. Cache by the + * original version before the lookup, if it's changed since then we'll cache a bad + * entry. Bad entries and CAS failures aren't a concern as subsequent lookups will + * sort themselves out. + */ + table.compareAndSet(index, entry, + new MethodCacheEntry(versionTag, name, where[0], value)); } return value; } @@ -2255,8 +2342,8 @@ /** * Determine if name is cacheable. * - * Since the cache can keep references to names alive longer than usual, it avoids - * caching unusually large strings. + * Since the cache can keep references to names alive longer than usual, it avoids caching + * unusually large strings. */ private static boolean isCacheableName(String name) { return name.length() <= 100; @@ -2309,8 +2396,8 @@ return retVal; } } - //bases cannot be null - for (PyObject ob: bases) { + // bases cannot be null + for (PyObject ob : bases) { if (ob != null) { retVal = visit.visit(ob, arg); if (retVal != 0) { @@ -2325,16 +2412,16 @@ } } if (mro != null) { - for (PyObject ob: mro) { + for (PyObject ob : mro) { retVal = visit.visit(ob, arg); if (retVal != 0) { return retVal; } } } - //don't traverse subclasses since they are weak refs. - //ReferenceQueue subclasses_refq = new ReferenceQueue(); - //Set> subclasses = Generic.set(); + // Don't traverse subclasses since they are weak refs. + // ReferenceQueue subclasses_refq = new ReferenceQueue(); + // Set> subclasses = Generic.set(); return 0; } @@ -2343,14 +2430,14 @@ if (ob == null) { return false; } - //bases cannot be null - for (PyObject obj: bases) { + // bases cannot be null + for (PyObject obj : bases) { if (obj == ob) { return true; } } if (mro != null) { - for (PyObject obj: mro) { + for (PyObject obj : mro) { if (obj == ob) { return true; } -- Repository URL: https://hg.python.org/jython