From: <cg...@us...> - 2008-10-22 08:32:04
|
Revision: 5504 http://jython.svn.sourceforge.net/jython/?rev=5504&view=rev Author: cgroves Date: 2008-10-22 08:27:42 +0000 (Wed, 22 Oct 2008) Log Message: ----------- Expose PyGenerator so we can control the visibility of gi_running. test_generators checks on __doc__ from next on generators, so this commit adds docstrings to exposed methods to satisfy that requirement. Modified Paths: -------------- trunk/jython/CoreExposed.includes trunk/jython/src/org/python/core/PyBuiltinCallable.java trunk/jython/src/org/python/core/PyBuiltinFunction.java trunk/jython/src/org/python/core/PyGenerator.java trunk/jython/src/org/python/core/PyIterator.java trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/expose/ExposedMethod.java trunk/jython/src/org/python/expose/generate/ClassMethodExposer.java trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java trunk/jython/src/org/python/expose/generate/InstanceMethodExposer.java trunk/jython/src/org/python/expose/generate/MethodExposer.java trunk/jython/tests/java/org/python/expose/generate/MethodExposerTest.java Modified: trunk/jython/CoreExposed.includes =================================================================== --- trunk/jython/CoreExposed.includes 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/CoreExposed.includes 2008-10-22 08:27:42 UTC (rev 5504) @@ -16,6 +16,7 @@ org/python/core/PyFloat.class org/python/core/PyFrozenSet.class org/python/core/PyFunction.class +org/python/core/PyGenerator.class org/python/core/PyInteger.class org/python/core/PyList.class org/python/core/PyLong.class Modified: trunk/jython/src/org/python/core/PyBuiltinCallable.java =================================================================== --- trunk/jython/src/org/python/core/PyBuiltinCallable.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/core/PyBuiltinCallable.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -9,6 +9,8 @@ protected Info info; + protected String doc; + protected PyBuiltinCallable(PyType type, Info info) { super(type); this.info = info; @@ -29,8 +31,8 @@ } @ExposedGet(name = "__doc__") - public PyObject fastGetDoc() { - return Py.None; + public String fastGetDoc() { + return doc; } @ExposedGet(name = "__module__") Modified: trunk/jython/src/org/python/core/PyBuiltinFunction.java =================================================================== --- trunk/jython/src/org/python/core/PyBuiltinFunction.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/core/PyBuiltinFunction.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -4,21 +4,15 @@ public class PyBuiltinFunction extends PyBuiltinCallable implements ExposeAsSuperclass { - private PyString doc; - protected PyBuiltinFunction(String name, String doc) { this(name, -1, -1, doc); } protected PyBuiltinFunction(String name, int minargs, int maxargs, String doc) { super(new DefaultInfo(name, minargs, maxargs)); - this.doc = doc == null ? null : Py.newString(doc); + this.doc = doc == null ? null : doc; } - public PyObject fastGetDoc() { - return doc; - } - public boolean isMappingType() { return false; } Modified: trunk/jython/src/org/python/core/PyGenerator.java =================================================================== --- trunk/jython/src/org/python/core/PyGenerator.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/core/PyGenerator.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -1,39 +1,33 @@ -// Copyright 2002 Finn Bock - package org.python.core; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedType; + +@ExposedType(name="generator", base=PyObject.class) public class PyGenerator extends PyIterator { - public PyFrame gi_frame; - PyObject closure; - public boolean gi_running; + + @ExposedGet + protected PyFrame gi_frame; + + @ExposedGet + protected boolean gi_running; + private PyException generatorExit; + private PyObject closure; + public PyGenerator(PyFrame frame, PyObject closure) { - this.gi_frame = frame; + gi_frame = frame; this.closure = closure; - this.gi_running = false; - // Create an exception instance while we have a frame to create it from. - // When the GC runs it doesn't have any associated thread state. - // this is necessary for finalize calling close on the generator - this.generatorExit = Py.makeException(Py.GeneratorExit); - } - private static final String[] __members__ = { - "close", "gi_frame", "gi_running", "next", "send", "throw" - }; - - public PyObject __dir__() { - PyString members[] = new PyString[__members__.length]; - for (int i = 0; i < __members__.length; i++) - members[i] = new PyString(__members__[i]); - PyList ret = new PyList(members); - PyDictionary accum = new PyDictionary(); - addKeys(accum, "__dict__"); - ret.extend(accum.keys()); - ret.sort(); - return ret; + // Create an exception instance while we have a frame to create it from. When the GC runs it + // doesn't have any associated thread state. this is necessary for finalize calling close on + // the generator + generatorExit = Py.makeException(Py.GeneratorExit); } + @ExposedMethod public PyObject send(PyObject value) { if (gi_frame == null) { throw Py.StopIteration(""); @@ -45,26 +39,12 @@ return next(); } - private PyObject raiseException(PyException ex) { - if (gi_frame == null || gi_frame.f_lasti == 0) { - throw ex; - } - gi_frame.setGeneratorInput(ex); - return next(); - } - - public PyObject throw$(PyObject type) { - return raiseException(Py.makeException(type)); - } - - public PyObject throw$(PyObject type, PyObject value) { - return raiseException(Py.makeException(type, value)); - } - + @ExposedMethod(names="throw", defaults={"null", "null"}) public PyObject throw$(PyObject type, PyObject value, PyTraceback tb) { return raiseException(Py.makeException(type, value, tb)); } + @ExposedMethod public PyObject close() { try { raiseException(generatorExit); @@ -77,25 +57,43 @@ return Py.None; } + @Override + @ExposedMethod(doc="x.next() -> the next value, or raise StopIteration") + public PyObject next() { + return super.next(); + } + + @Override + @ExposedMethod + public PyObject __iter__() { + return this; + } + + private PyObject raiseException(PyException ex) { + if (gi_frame == null || gi_frame.f_lasti == 0) { + throw ex; + } + gi_frame.setGeneratorInput(ex); + return next(); + } + + @Override protected void finalize() throws Throwable { - if (gi_frame == null || gi_frame.f_lasti == -1) + if (gi_frame == null || gi_frame.f_lasti == -1) return; try { close(); } catch (PyException e) { // PEP 342 specifies that if an exception is raised by close, - // we output to stderr and then forget about it; + // we output to stderr and then forget about it; String className = PyException.exceptionClassName(e.type); int lastDot = className.lastIndexOf('.'); if (lastDot != -1) { className = className.substring(lastDot + 1); } - PyString m = Py.newString( - String.format("Exception %s: %s in %s", - className, - e.value.__repr__().toString(), - this.__repr__().toString())); - Py.println(Py.getSystemState().stderr, m); + String msg = String.format("Exception %s: %s in %s", className, e.value.__repr__() + .toString(), __repr__().toString()); + Py.println(Py.getSystemState().stderr, Py.newString(msg)); } catch (Throwable e) { // but we currently ignore any Java exception completely. perhaps we // can also output something meaningful too? @@ -110,7 +108,7 @@ if (gi_frame == null) { return null; } - + if (gi_frame.f_lasti == -1) { gi_frame = null; return null; Modified: trunk/jython/src/org/python/core/PyIterator.java =================================================================== --- trunk/jython/src/org/python/core/PyIterator.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/core/PyIterator.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -28,9 +28,8 @@ return this; } - public static PyString __doc__next = new PyString( - "x.next() -> the next value, or raise StopIteration" - ); + public static PyString __doc__next = + new PyString("x.next() -> the next value, or raise StopIteration"); /** * The exposed next method. Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/core/PyObject.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -3539,7 +3539,9 @@ } public void __set__(PyObject obj, PyObject value) { - throw Py.AttributeError("object internal __set__ impl is abstract"); + if (!_doset(obj, value)) { + throw Py.AttributeError("object internal __set__ impl is abstract"); + } } public void __delete__(PyObject obj) { Modified: trunk/jython/src/org/python/expose/ExposedMethod.java =================================================================== --- trunk/jython/src/org/python/expose/ExposedMethod.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/expose/ExposedMethod.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -7,24 +7,29 @@ /** * Indicates a method should be exposed to Python code. - * + * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExposedMethod { /** - * @return the names to expose this method as. Defaults to just actual name of the method. + * Returns the names to expose this method as. Defaults to the name of the method. */ String[] names() default {}; /** - * @return default arguments. Starts at the number of arguments - defaults.length. + * Returns default arguments. Starts at the number of arguments - defaults.length. */ String[] defaults() default {}; /** - * @return - how to expose this method. See {@link MethodType} for the options. + * Returns how to expose this method. See {@link MethodType} for the options. */ MethodType type() default MethodType.DEFAULT; -} + + /** + * Returns the __doc__ String for this method. + */ + String doc() default ""; +} \ No newline at end of file Modified: trunk/jython/src/org/python/expose/generate/ClassMethodExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ClassMethodExposer.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/expose/generate/ClassMethodExposer.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -2,7 +2,6 @@ import org.python.objectweb.asm.Type; import org.python.core.PyBuiltinClassMethodNarrow; -import org.python.core.PyBuiltinMethodNarrow; public class ClassMethodExposer extends MethodExposer { @@ -14,7 +13,8 @@ String desc, String typeName, String[] asNames, - String[] defaults) { + String[] defaults, + String doc) { super(onType, methodName, getArgs(onType, methodName, desc), @@ -22,7 +22,8 @@ typeName, asNames, defaults, - PyBuiltinClassMethodNarrow.class); + PyBuiltinClassMethodNarrow.class, + doc); actualArgs = Type.getArgumentTypes(desc); } Modified: trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -137,6 +137,15 @@ class ExposedMethodVisitor extends RestrictiveAnnotationVisitor { @Override + public void visit(String name, Object value) { + if (name.equals("doc")) { + doc = (String)value; + } else { + super.visit(name, value); + } + } + + @Override public AnnotationVisitor visitArray(String name) { if(name.equals("names")) { return new StringArrayBuilder() { @@ -173,6 +182,8 @@ private String[] defaults = new String[0]; private MethodType type = MethodType.DEFAULT; + + private String doc = ""; } @Override @@ -185,7 +196,8 @@ typeName, methVisitor.names, methVisitor.defaults, - methVisitor.type)); + methVisitor.type, + methVisitor.doc)); } if(newExp != null) { handleNewExposer(newExp); @@ -197,7 +209,8 @@ methodDesc, typeName, classMethVisitor.names, - classMethVisitor.defaults)); + classMethVisitor.defaults, + classMethVisitor.doc)); } super.visitEnd(); } Modified: trunk/jython/src/org/python/expose/generate/InstanceMethodExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/InstanceMethodExposer.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/expose/generate/InstanceMethodExposer.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -27,7 +27,8 @@ typeName, new String[0], new String[0], - MethodType.DEFAULT); + MethodType.DEFAULT, + null); } public InstanceMethodExposer(Type onType, @@ -37,7 +38,8 @@ String typeName, String[] asNames, String[] defaults, - MethodType type) { + MethodType type, + String doc) { super(onType, methodName, Type.getArgumentTypes(desc), @@ -45,7 +47,8 @@ typeName, asNames, defaults, - isWide(desc) ? PyBuiltinMethod.class : PyBuiltinMethodNarrow.class); + isWide(desc) ? PyBuiltinMethod.class : PyBuiltinMethodNarrow.class, + doc); if ((access & ACC_STATIC) != 0) { throwInvalid("@ExposedMethod can't be applied to static methods"); } Modified: trunk/jython/src/org/python/expose/generate/MethodExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/MethodExposer.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/src/org/python/expose/generate/MethodExposer.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -1,12 +1,11 @@ package org.python.expose.generate; import org.python.objectweb.asm.Type; -import org.python.expose.MethodType; public abstract class MethodExposer extends Exposer { protected String[] defaults; - + protected final String[] asNames; protected final String prefix, typeName; @@ -17,6 +16,8 @@ protected final Type onType, returnType; + protected final String doc; + public MethodExposer(Type onType, String methodName, Type[] args, @@ -24,12 +25,14 @@ String typeName, String[] asNames, String[] defaults, - Class superClass) { + Class superClass, + String doc) { super(superClass, onType.getClassName() + "$" + methodName + "_exposer"); this.onType = onType; this.methodName = methodName; this.args = args; this.typeName = typeName; + this.doc = doc; String prefix = typeName; int lastDot = prefix.lastIndexOf('.'); if (lastDot != -1) { @@ -64,7 +67,7 @@ } return asNames; } - + protected void generate() { generateNamedConstructor(); generateFullConstructor(); @@ -85,6 +88,12 @@ mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 3); superConstructor(PYTYPE, PYOBJ, BUILTIN_INFO); + mv.visitVarInsn(ALOAD, 0); + mv.visitLdcInsn(doc); + mv.visitFieldInsn(PUTFIELD, + BUILTIN_FUNCTION.getInternalName(), + "doc", + STRING.getDescriptor()); endConstructor(); } @@ -99,6 +108,12 @@ mv.visitLdcInsn(args.length + 1); superConstructor(STRING, INT, INT); } + mv.visitVarInsn(ALOAD, 0); + mv.visitLdcInsn(doc); + mv.visitFieldInsn(PUTFIELD, + BUILTIN_FUNCTION.getInternalName(), + "doc", + STRING.getDescriptor()); endConstructor(); } @@ -126,7 +141,7 @@ toPy(returnType); endMethod(ARETURN); } - + private boolean hasDefault(int argIndex) { return defaults.length - args.length + argIndex >= 0; } Modified: trunk/jython/tests/java/org/python/expose/generate/MethodExposerTest.java =================================================================== --- trunk/jython/tests/java/org/python/expose/generate/MethodExposerTest.java 2008-10-22 04:53:59 UTC (rev 5503) +++ trunk/jython/tests/java/org/python/expose/generate/MethodExposerTest.java 2008-10-22 08:27:42 UTC (rev 5504) @@ -6,7 +6,6 @@ import org.python.core.Py; import org.python.core.PyBuiltinCallable; import org.python.core.PyException; -import org.python.core.PyObject; import org.python.expose.MethodType; public class MethodExposerTest extends InterpTestCase implements Opcodes, PyTypes { @@ -167,7 +166,8 @@ "simpleexposed", new String[0], new String[] {"X"}, - MethodType.DEFAULT); + MethodType.DEFAULT, + ""); fail("Shouldn't be able to create the exposer with a default value"); } catch (InvalidExposingException ite) {} } @@ -197,7 +197,8 @@ new Type[] {PYTYPE}), "simpleexposed", new String[0], - new String[0]); + new String[0], + ""); PyBuiltinCallable bound = createBound(exp); assertEquals("a", bound.__call__().toString()); } @@ -212,7 +213,8 @@ PYOBJ}), "simpleexposed", new String[0], - new String[] {"null", "Py.None"}); + new String[] {"null", "Py.None"}, + ""); PyBuiltinCallable bound = createBound(exp); assertEquals(0, bound.__call__().asInt()); assertEquals(1, bound.__call__(Py.newString("hello")).asInt()); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |