You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(107) |
Dec
(67) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(76) |
Feb
(125) |
Mar
(72) |
Apr
(13) |
May
(18) |
Jun
(12) |
Jul
(129) |
Aug
(47) |
Sep
(1) |
Oct
(36) |
Nov
(128) |
Dec
(124) |
2002 |
Jan
(59) |
Feb
|
Mar
(14) |
Apr
(14) |
May
(72) |
Jun
(9) |
Jul
(3) |
Aug
(5) |
Sep
(18) |
Oct
(65) |
Nov
(28) |
Dec
(12) |
2003 |
Jan
(10) |
Feb
(2) |
Mar
(4) |
Apr
(33) |
May
(21) |
Jun
(9) |
Jul
(29) |
Aug
(34) |
Sep
(4) |
Oct
(8) |
Nov
(15) |
Dec
(4) |
2004 |
Jan
(26) |
Feb
(12) |
Mar
(11) |
Apr
(9) |
May
(7) |
Jun
|
Jul
(5) |
Aug
|
Sep
(3) |
Oct
(7) |
Nov
(1) |
Dec
(10) |
2005 |
Jan
(2) |
Feb
(72) |
Mar
(16) |
Apr
(39) |
May
(48) |
Jun
(97) |
Jul
(57) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(100) |
Dec
(24) |
2006 |
Jan
(15) |
Feb
(34) |
Mar
(33) |
Apr
(31) |
May
(79) |
Jun
(64) |
Jul
(41) |
Aug
(64) |
Sep
(31) |
Oct
(46) |
Nov
(55) |
Dec
(37) |
2007 |
Jan
(32) |
Feb
(61) |
Mar
(11) |
Apr
(58) |
May
(46) |
Jun
(30) |
Jul
(94) |
Aug
(93) |
Sep
(86) |
Oct
(69) |
Nov
(125) |
Dec
(177) |
2008 |
Jan
(169) |
Feb
(97) |
Mar
(74) |
Apr
(113) |
May
(120) |
Jun
(334) |
Jul
(215) |
Aug
(237) |
Sep
(72) |
Oct
(189) |
Nov
(126) |
Dec
(160) |
2009 |
Jan
(180) |
Feb
(45) |
Mar
(98) |
Apr
(140) |
May
(151) |
Jun
(71) |
Jul
(107) |
Aug
(119) |
Sep
(73) |
Oct
(121) |
Nov
(14) |
Dec
(6) |
2010 |
Jan
(13) |
Feb
(9) |
Mar
(10) |
Apr
(64) |
May
(3) |
Jun
(16) |
Jul
(7) |
Aug
(23) |
Sep
(17) |
Oct
(37) |
Nov
(5) |
Dec
(8) |
2011 |
Jan
(10) |
Feb
(11) |
Mar
(77) |
Apr
(11) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <wme...@us...> - 2009-08-26 10:33:28
|
Revision: 6723 http://jython.svn.sourceforge.net/jython/?rev=6723&view=rev Author: wmeissner Date: 2009-08-26 10:33:22 +0000 (Wed, 26 Aug 2009) Log Message: ----------- Use type() to create Array classes Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-26 10:08:56 UTC (rev 6722) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-26 10:33:22 UTC (rev 6723) @@ -6,7 +6,8 @@ return type.__new__(cls, name, bases, dict) def __mul__(self, len): - return _ArrayType(jffi.Type.Array(self._jffi_type, len)) + dict = { '_jffi_type': jffi.Type.Array(self, len) } + return type("%s_%d" % (self.__name__, len), (_ArrayCData,), dict) class _ScalarCData(jffi.ScalarCData): __metaclass__ = _CTypeMetaClass @@ -16,11 +17,8 @@ size = classmethod(size) -class _ArrayType(object): - def __init__(self, jffi_type): - self._jffi_type = jffi_type - - def __call__(self, *args): +class _ArrayCData(object): + def __init__(self, *args): raise NotImplementedError("instantiating arrays is not implemented yet") def __len__(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-26 10:09:07
|
Revision: 6722 http://jython.svn.sourceforge.net/jython/?rev=6722&view=rev Author: wmeissner Date: 2009-08-26 10:08:56 +0000 (Wed, 26 Aug 2009) Log Message: ----------- Fixup CType exposure Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/src/org/python/modules/jffi/CType.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-08-26 07:18:30 UTC (rev 6721) +++ branches/ctypes-jffi/CoreExposed.includes 2009-08-26 10:08:56 UTC (rev 6722) @@ -53,14 +53,14 @@ org/python/modules/_functools/PyPartial.class org/python/modules/_hashlib$Hash.class org/python/modules/jffi/CData.class +org/python/modules/jffi/CType.class +org/python/modules/jffi/CType$Array.class +org/python/modules/jffi/CType$Pointer.class org/python/modules/jffi/DynamicLibrary.class org/python/modules/jffi/DynamicLibrary$Symbol.class org/python/modules/jffi/Function.class org/python/modules/jffi/Pointer.class org/python/modules/jffi/ScalarCData.class -org/python/modules/jffi/Type.class -org/python/modules/jffi/Type$Array.class -org/python/modules/jffi/Type$Pointer.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class org/python/modules/_weakref/CallableProxyType.class Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-08-26 07:18:30 UTC (rev 6721) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-08-26 10:08:56 UTC (rev 6722) @@ -6,14 +6,13 @@ import org.python.core.Py; import org.python.core.PyNewWrapper; import org.python.core.PyObject; -import org.python.core.PyObjectDerived; import org.python.core.PyType; import org.python.expose.ExposeAsSuperclass; import org.python.expose.ExposedGet; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; -@ExposedType(name = "jffi.Type", base = PyObjectDerived.class) +@ExposedType(name = "jffi.Type", base = PyObject.class) public class CType extends PyObject { public static final PyType TYPE = PyType.fromClass(CType.class); static { @@ -92,16 +91,30 @@ } } + private static CType typeOf(PyObject obj) { + if (obj instanceof CType) { + return (CType) obj; + } + + PyObject jffi_type = obj.__getattr__("_jffi_type"); + if (!(jffi_type instanceof CType)) { + throw Py.TypeError("invalid _jffi_type"); + } + return (CType) jffi_type; + } + @ExposedType(name = "jffi.Type.Array", base = CType.class) static final class Array extends CType { public static final PyType TYPE = PyType.fromClass(Array.class); final CType componentType; - + final PyObject pyComponentType; + @ExposedGet public final int length; - public Array(CType componentType, int length) { + public Array(PyObject pyComponentType, CType componentType, int length) { super(NativeType.ARRAY, new com.kenai.jffi.Array(componentType.jffiType, length), null); + this.pyComponentType = pyComponentType; this.componentType = componentType; this.length = length; } @@ -114,11 +127,7 @@ throw Py.TypeError(String.format("__init__() takes exactly 2 arguments (%d given)", args.length)); } - if (!(args[0] instanceof CType)) { - throw Py.TypeError("expected jffi.Type"); - } - - return new Array((CType) args[0], args[1].asInt()); + return new Array(args[0], typeOf(args[0]), args[1].asInt()); } @Override @@ -128,7 +137,7 @@ @Override public final String toString() { - return String.format("<jffi.Type.Array length=%d>", length); + return String.format("<ctypes.Array elem_type=%s length=%d>", pyComponentType.toString(), length); } } @@ -142,10 +151,11 @@ final PyType pyComponentType; final MemoryOp componentMemoryOp; - Pointer(PyType subtype, CType componentType, PyType pyComponentType) { + Pointer(PyType subtype, PyType pyComponentType, CType componentType) { super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, MemoryOp.POINTER); + this.pyComponentType = pyComponentType; this.componentType = componentType; - this.pyComponentType = pyComponentType; + if (pyComponentType.isSubType(ScalarCData.TYPE)) { this.componentMemoryOp = new ScalarOp(MemoryOp.getMemoryOp(componentType.getNativeType()), pyComponentType); } else { @@ -163,18 +173,15 @@ return p; } - if (args.length < 1) { + if (args.length != 1) { throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); } - if (!(args[0] instanceof CType)) { - throw Py.TypeError("expected jffi.Type"); + if (!(args[0] instanceof PyType)) { + throw Py.TypeError("expected ctypes class"); } - if (args.length > 1 && !(args[1] instanceof PyType)) { - throw Py.TypeError("expected type"); - } - p = new Pointer(subtype, (CType) args[0], args.length > 1 ? (PyType) args[1] : Py.None.getType()); + p = new Pointer(subtype, (PyType) args[0], typeOf(args[0])); typeCache.put(args[0], p); return p; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-26 07:18:44
|
Revision: 6721 http://jython.svn.sourceforge.net/jython/?rev=6721&view=rev Author: wmeissner Date: 2009-08-26 07:18:30 +0000 (Wed, 26 Aug 2009) Log Message: ----------- Rename Type to CType in java code Modified Paths: -------------- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/Function.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java Removed Paths: ------------- branches/ctypes-jffi/src/org/python/modules/jffi/Type.java Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-08-26 05:25:19 UTC (rev 6720) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -14,12 +14,12 @@ public static final PyType TYPE = PyType.fromClass(CData.class); final MemoryOp memoryOp; - final Type type; + final CType type; private Memory contentMemory; private PyObject value; - CData(PyType subtype, Type type, MemoryOp memoryOp) { + CData(PyType subtype, CType type, MemoryOp memoryOp) { super(subtype); this.type = type; this.memoryOp = memoryOp; Copied: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java (from rev 6720, branches/ctypes-jffi/src/org/python/modules/jffi/Type.java) =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -0,0 +1,229 @@ + +package org.python.modules.jffi; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.python.core.Py; +import org.python.core.PyNewWrapper; +import org.python.core.PyObject; +import org.python.core.PyObjectDerived; +import org.python.core.PyType; +import org.python.expose.ExposeAsSuperclass; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.Type", base = PyObjectDerived.class) +public class CType extends PyObject { + public static final PyType TYPE = PyType.fromClass(CType.class); + static { + TYPE.fastGetDict().__setitem__("Array", Array.TYPE); + TYPE.fastGetDict().__setitem__("Pointer", Pointer.TYPE); + } + public static final CType VOID = primitive(NativeType.VOID); + public static final CType BYTE = primitive(NativeType.BYTE); + public static final CType UBYTE = primitive(NativeType.UBYTE); + public static final CType SHORT = primitive(NativeType.SHORT); + public static final CType USHORT = primitive(NativeType.USHORT); + public static final CType INT = primitive(NativeType.INT); + public static final CType UINT = primitive(NativeType.UINT); + public static final CType LONGLONG = primitive(NativeType.LONGLONG); + public static final CType ULONGLONG = primitive(NativeType.ULONGLONG); + public static final CType LONG = primitive(NativeType.LONG); + public static final CType ULONG = primitive(NativeType.ULONG); + public static final CType FLOAT = primitive(NativeType.FLOAT); + public static final CType DOUBLE = primitive(NativeType.DOUBLE); + public static final CType POINTER = primitive(NativeType.POINTER); + public static final CType STRING = primitive(NativeType.STRING); + + final com.kenai.jffi.Type jffiType; + + final NativeType nativeType; + + /** Size of this type in bytes */ + @ExposedGet + public final int size; + + /** Minimum alignment of this type in bytes */ + @ExposedGet + public final int alignment; + + /** The <tt>MemoryOp</tt> used to read/write items of this type */ + private final MemoryOp memoryOp; + + CType(NativeType type, com.kenai.jffi.Type jffiType, MemoryOp memoryOp) { + this.nativeType = type; + this.jffiType = jffiType; + this.size = jffiType.size(); + this.alignment = jffiType.alignment(); + this.memoryOp = memoryOp; + } + + public NativeType getNativeType() { + return nativeType; + } + + MemoryOp getMemoryOp() { + return memoryOp; + } + + public int alignment() { + return alignment; + } + + public int size() { + return size; + } + + static final CType primitive(NativeType type) { + CType t = new Builtin(type, NativeType.jffiType(type)); + CType.TYPE.fastGetDict().__setitem__(type.name(), t); + return t; + } + + static final class Builtin extends CType implements ExposeAsSuperclass { + public Builtin(NativeType type, com.kenai.jffi.Type jffiType) { + super(type, jffiType, MemoryOp.getMemoryOp(type)); + } + + @Override + public final String toString() { + return "<jffi.Type." + nativeType.name() + ">"; + } + } + + @ExposedType(name = "jffi.Type.Array", base = CType.class) + static final class Array extends CType { + public static final PyType TYPE = PyType.fromClass(Array.class); + final CType componentType; + + @ExposedGet + public final int length; + + public Array(CType componentType, int length) { + super(NativeType.ARRAY, new com.kenai.jffi.Array(componentType.jffiType, length), null); + this.componentType = componentType; + this.length = length; + } + + @ExposedNew + public static PyObject Array_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + if (args.length != 2) { + throw Py.TypeError(String.format("__init__() takes exactly 2 arguments (%d given)", args.length)); + } + + if (!(args[0] instanceof CType)) { + throw Py.TypeError("expected jffi.Type"); + } + + return new Array((CType) args[0], args[1].asInt()); + } + + @Override + public int __len__() { + return length; + } + + @Override + public final String toString() { + return String.format("<jffi.Type.Array length=%d>", length); + } + } + + @ExposedType(name = "jffi.Type.Pointer", base = CType.class) + final static class Pointer extends CType { + public static final PyType TYPE = PyType.fromClass(Pointer.class); + private static final ConcurrentMap<PyObject, Pointer> typeCache + = new ConcurrentHashMap<PyObject, Pointer>(); + + final CType componentType; + final PyType pyComponentType; + final MemoryOp componentMemoryOp; + + Pointer(PyType subtype, CType componentType, PyType pyComponentType) { + super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, MemoryOp.POINTER); + this.componentType = componentType; + this.pyComponentType = pyComponentType; + if (pyComponentType.isSubType(ScalarCData.TYPE)) { + this.componentMemoryOp = new ScalarOp(MemoryOp.getMemoryOp(componentType.getNativeType()), pyComponentType); + } else { + throw Py.TypeError("pointer only supported for scalar types"); + } + + } + + @ExposedNew + public static PyObject Pointer_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + Pointer p = typeCache.get(args[0]); + if (p != null) { + return p; + } + + if (args.length < 1) { + throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); + } + + if (!(args[0] instanceof CType)) { + throw Py.TypeError("expected jffi.Type"); + } + + if (args.length > 1 && !(args[1] instanceof PyType)) { + throw Py.TypeError("expected type"); + } + p = new Pointer(subtype, (CType) args[0], args.length > 1 ? (PyType) args[1] : Py.None.getType()); + typeCache.put(args[0], p); + + return p; + } + + @Override + public final String toString() { + return String.format("<jffi.Type.Pointer component_type=%s>", componentType.toString()); + } + + @Override + public PyObject __call__(PyObject value) { + if (value == Py.None) { + + return new org.python.modules.jffi.Pointer(new NullMemory(), componentMemoryOp); + + } else if (value.getType().isSubType(pyComponentType) && value instanceof CData) { + + return new org.python.modules.jffi.Pointer((DirectMemory) ((CData) value).getContentMemory(), componentMemoryOp); + + } else { + throw Py.TypeError("expected " + pyComponentType.getName() + " instead of " + value.getType().getName()); + } + } + + private static final class ScalarOp extends MemoryOp { + private final MemoryOp op; + private final PyType type; + + public ScalarOp(MemoryOp op, PyType type) { + this.op = op; + this.type = type; + } + + public final void put(Memory mem, long offset, PyObject value) { + op.put(mem, offset, value); + } + + public final PyObject get(Memory mem, long offset) { + PyObject result = type.__call__(op.get(mem, offset)); + // + // Point the CData to the backing memory so all value gets/sets + // update the same memory this pointer points to + // + if (result instanceof CData) { + ((CData) result).setContentMemory(mem); + } + return result; + } + } + } +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-26 05:25:19 UTC (rev 6720) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -19,7 +19,7 @@ private DefaultInvokerFactory() {} - final Invoker createInvoker(com.kenai.jffi.Function function, Type[] parameterTypes, Type returnType) { + final Invoker createInvoker(com.kenai.jffi.Function function, CType[] parameterTypes, CType returnType) { ParameterMarshaller[] marshallers = new ParameterMarshaller[parameterTypes.length]; for (int i = 0; i < marshallers.length; ++i) { @@ -27,7 +27,7 @@ } - if (returnType instanceof Type.Builtin) { + if (returnType instanceof CType.Builtin) { switch (returnType.getNativeType()) { case VOID: return new VoidInvoker(function, marshallers); @@ -128,8 +128,8 @@ } } - private static final ParameterMarshaller getMarshaller(Type type) { - if (type instanceof Type.Builtin) { + private static final ParameterMarshaller getMarshaller(CType type) { + if (type instanceof CType.Builtin) { return getMarshaller(type.getNativeType()); } else { throw Py.RuntimeError("Unsupported parameter type: " + type); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-08-26 05:25:19 UTC (rev 6720) +++ branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -53,7 +53,7 @@ * @param parameterTypes The parameter types of the native function. * @return <tt>true</tt> if the method can be handled as a fast int method. */ - final boolean isFastIntMethod(Type returnType, Type[] parameterTypes) { + final boolean isFastIntMethod(CType returnType, CType[] parameterTypes) { for (int i = 0; i < parameterTypes.length; ++i) { if (!isFastIntParam(parameterTypes[i])) { return false; @@ -68,8 +68,8 @@ * @param type The result type. * @return <tt>true</tt> if <tt>type</tt> can be returned as an integer. */ - final boolean isFastIntResult(Type type) { - if (type instanceof Type.Builtin) { + final boolean isFastIntResult(CType type) { + if (type instanceof CType.Builtin) { switch (type.getNativeType()) { case VOID: case BYTE: @@ -99,8 +99,8 @@ * @param type The parameter type. * @return <tt>true</tt> if <tt>type</tt> can be passed as an integer. */ - final boolean isFastIntParam(Type paramType) { - if (paramType instanceof Type.Builtin) { + final boolean isFastIntParam(CType paramType) { + if (paramType instanceof CType.Builtin) { switch (paramType.getNativeType()) { case BYTE: case UBYTE: @@ -132,7 +132,7 @@ * @param returnType The result type the function will return * @return A new {@link Invoker} instance. */ - final Invoker createInvoker(Function function, Type[] parameterTypes, Type returnType) { + final Invoker createInvoker(Function function, CType[] parameterTypes, CType returnType) { IntParameterConverter[] parameterConverters = new IntParameterConverter[parameterTypes.length]; for (int i = 0; i < parameterConverters.length; ++i) { @@ -171,8 +171,8 @@ * @param type The python C type * @return An <tt>IntParameterConverter</tt> instance. */ - final IntParameterConverter getIntParameterConverter(Type type) { - if (type instanceof Type.Builtin) { + final IntParameterConverter getIntParameterConverter(CType type) { + if (type instanceof CType.Builtin) { return getIntParameterConverter(type.getNativeType()); } throw Py.TypeError("cannot convert objects of type " + type + " to int"); @@ -237,8 +237,8 @@ * @param type The object type. * @return An <tt>IntResultConverter</tt> instance. */ - final IntResultConverter getIntResultConverter(Type type) { - return type instanceof Type.Builtin ? getIntResultConverter(type.getNativeType()) : null; + final IntResultConverter getIntResultConverter(CType type) { + return type instanceof CType.Builtin ? getIntResultConverter(type.getNativeType()) : null; } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Function.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Function.java 2009-08-26 05:25:19 UTC (rev 6720) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Function.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -21,8 +21,8 @@ private final PyStringMap dict = new PyStringMap(); - private volatile Type returnType = Type.SINT32; - private volatile Type[] parameterTypes = null; + private volatile CType returnType = CType.INT; + private volatile CType[] parameterTypes = null; private Invoker invoker = null; @ExposedGet @@ -110,17 +110,17 @@ @ExposedSet(name = "_jffi_restype") public void setReturnType(PyObject returnType) { - if (!(returnType instanceof Type)) { + if (!(returnType instanceof CType)) { throw Py.TypeError("wrong argument type (expected jffi.Type)"); } this.invoker = null; // invalidate old invoker - this.returnType = (Type) returnType; + this.returnType = (CType) returnType; } @ExposedGet(name = "_jffi_argtypes") public PyObject getParameterTypes() { - return new PyList(parameterTypes != null ? parameterTypes : new Type[0]); + return new PyList(parameterTypes != null ? parameterTypes : new CType[0]); } @ExposedSet(name = "_jffi_argtypes") @@ -135,13 +135,13 @@ throw Py.TypeError("wrong argument type (expected list of jffi.Type)"); } - Type[] paramTypes = new Type[((PyList) parameterTypes).size()]; + CType[] paramTypes = new CType[((PyList) parameterTypes).size()]; for (int i = 0; i < paramTypes.length; ++i) { PyObject t = ((PyList) parameterTypes).pyget(i); - if (!(t instanceof Type)) { + if (!(t instanceof CType)) { throw Py.TypeError(String.format("wrong argument type for parameter %d (expected jffi.Type)", i)); } - paramTypes[i] = (Type) t; + paramTypes[i] = (CType) t; } this.invoker = null; // invalidate old invoker @@ -156,7 +156,7 @@ return createInvoker(address, returnType, parameterTypes); } - private synchronized final Invoker createInvoker(long address, Type returnType, Type[] parameterTypes) { + private synchronized final Invoker createInvoker(long address, CType returnType, CType[] parameterTypes) { if (parameterTypes == null) { throw Py.NotImplementedError("variadic functions not supported yet; specify a parameter list"); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-26 05:25:19 UTC (rev 6720) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -21,11 +21,11 @@ PyObject jffi_type = subtype.__getattr__("_jffi_type"); - if (!(jffi_type instanceof Type.Builtin)) { + if (!(jffi_type instanceof CType.Builtin)) { throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); } - ScalarCData cdata = new ScalarCData(subtype, (Type.Builtin) jffi_type); + ScalarCData cdata = new ScalarCData(subtype, (CType.Builtin) jffi_type); // If an initial value was supplied, use it, else default to zero cdata.setValue(args.length > 0 ? args[0] : Py.newInteger(0)); @@ -33,7 +33,7 @@ return cdata; } - ScalarCData(PyType pyType, Type.Builtin type) { + ScalarCData(PyType pyType, CType.Builtin type) { super(pyType, type, type.getMemoryOp()); } Deleted: branches/ctypes-jffi/src/org/python/modules/jffi/Type.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Type.java 2009-08-26 05:25:19 UTC (rev 6720) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Type.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -1,229 +0,0 @@ - -package org.python.modules.jffi; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import org.python.core.Py; -import org.python.core.PyNewWrapper; -import org.python.core.PyObject; -import org.python.core.PyObjectDerived; -import org.python.core.PyType; -import org.python.expose.ExposeAsSuperclass; -import org.python.expose.ExposedGet; -import org.python.expose.ExposedNew; -import org.python.expose.ExposedType; - -@ExposedType(name = "jffi.Type", base = PyObjectDerived.class) -public class Type extends PyObject { - public static final PyType TYPE = PyType.fromClass(Type.class); - static { - TYPE.fastGetDict().__setitem__("Array", Array.TYPE); - TYPE.fastGetDict().__setitem__("Pointer", Pointer.TYPE); - } - public static final Type VOID = primitive(NativeType.VOID); - public static final Type SINT8 = primitive(NativeType.BYTE); - public static final Type UINT8 = primitive(NativeType.UBYTE); - public static final Type SINT16 = primitive(NativeType.SHORT); - public static final Type UINT16 = primitive(NativeType.USHORT); - public static final Type SINT32 = primitive(NativeType.INT); - public static final Type UINT32 = primitive(NativeType.UINT); - public static final Type SINT64 = primitive(NativeType.LONGLONG); - public static final Type UINT64 = primitive(NativeType.ULONGLONG); - public static final Type SLONG = primitive(NativeType.LONG); - public static final Type ULONG = primitive(NativeType.ULONG); - public static final Type FLOAT = primitive(NativeType.FLOAT); - public static final Type DOUBLE = primitive(NativeType.DOUBLE); - public static final Type POINTER = primitive(NativeType.POINTER); - public static final Type STRING = primitive(NativeType.STRING); - - final com.kenai.jffi.Type jffiType; - - final NativeType nativeType; - - /** Size of this type in bytes */ - @ExposedGet - public final int size; - - /** Minimum alignment of this type in bytes */ - @ExposedGet - public final int alignment; - - /** The <tt>MemoryOp</tt> used to read/write items of this type */ - private final MemoryOp memoryOp; - - Type(NativeType type, com.kenai.jffi.Type jffiType, MemoryOp memoryOp) { - this.nativeType = type; - this.jffiType = jffiType; - this.size = jffiType.size(); - this.alignment = jffiType.alignment(); - this.memoryOp = memoryOp; - } - - public NativeType getNativeType() { - return nativeType; - } - - MemoryOp getMemoryOp() { - return memoryOp; - } - - public int alignment() { - return alignment; - } - - public int size() { - return size; - } - - static final Type primitive(NativeType type) { - Type t = new Builtin(type, NativeType.jffiType(type)); - Type.TYPE.fastGetDict().__setitem__(type.name(), t); - return t; - } - - static final class Builtin extends Type implements ExposeAsSuperclass { - public Builtin(NativeType type, com.kenai.jffi.Type jffiType) { - super(type, jffiType, MemoryOp.getMemoryOp(type)); - } - - @Override - public final String toString() { - return "<jffi.Type." + nativeType.name() + ">"; - } - } - - @ExposedType(name = "jffi.Type.Array", base = Type.class) - static final class Array extends Type { - public static final PyType TYPE = PyType.fromClass(Array.class); - final Type componentType; - - @ExposedGet - public final int length; - - public Array(Type componentType, int length) { - super(NativeType.ARRAY, new com.kenai.jffi.Array(componentType.jffiType, length), null); - this.componentType = componentType; - this.length = length; - } - - @ExposedNew - public static PyObject Array_new(PyNewWrapper new_, boolean init, PyType subtype, - PyObject[] args, String[] keywords) { - - if (args.length != 2) { - throw Py.TypeError(String.format("__init__() takes exactly 2 arguments (%d given)", args.length)); - } - - if (!(args[0] instanceof Type)) { - throw Py.TypeError("expected jffi.Type"); - } - - return new Array((Type) args[0], args[1].asInt()); - } - - @Override - public int __len__() { - return length; - } - - @Override - public final String toString() { - return String.format("<jffi.Type.Array length=%d>", length); - } - } - - @ExposedType(name = "jffi.Type.Pointer", base = Type.class) - final static class Pointer extends Type { - public static final PyType TYPE = PyType.fromClass(Pointer.class); - private static final ConcurrentMap<PyObject, Pointer> typeCache - = new ConcurrentHashMap<PyObject, Pointer>(); - - final Type componentType; - final PyType pyComponentType; - final MemoryOp componentMemoryOp; - - Pointer(PyType subtype, Type componentType, PyType pyComponentType) { - super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, MemoryOp.POINTER); - this.componentType = componentType; - this.pyComponentType = pyComponentType; - if (pyComponentType.isSubType(ScalarCData.TYPE)) { - this.componentMemoryOp = new ScalarOp(MemoryOp.getMemoryOp(componentType.getNativeType()), pyComponentType); - } else { - throw Py.TypeError("pointer only supported for scalar types"); - } - - } - - @ExposedNew - public static PyObject Pointer_new(PyNewWrapper new_, boolean init, PyType subtype, - PyObject[] args, String[] keywords) { - - Pointer p = typeCache.get(args[0]); - if (p != null) { - return p; - } - - if (args.length < 1) { - throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); - } - - if (!(args[0] instanceof Type)) { - throw Py.TypeError("expected jffi.Type"); - } - - if (args.length > 1 && !(args[1] instanceof PyType)) { - throw Py.TypeError("expected type"); - } - p = new Pointer(subtype, (Type) args[0], args.length > 1 ? (PyType) args[1] : Py.None.getType()); - typeCache.put(args[0], p); - - return p; - } - - @Override - public final String toString() { - return String.format("<jffi.Type.Pointer component_type=%s>", componentType.toString()); - } - - @Override - public PyObject __call__(PyObject value) { - if (value == Py.None) { - - return new org.python.modules.jffi.Pointer(new NullMemory(), componentMemoryOp); - - } else if (value.getType().isSubType(pyComponentType) && value instanceof CData) { - - return new org.python.modules.jffi.Pointer((DirectMemory) ((CData) value).getContentMemory(), componentMemoryOp); - - } else { - throw Py.TypeError("expected " + pyComponentType.getName() + " instead of " + value.getType().getName()); - } - } - - private static final class ScalarOp extends MemoryOp { - private final MemoryOp op; - private final PyType type; - - public ScalarOp(MemoryOp op, PyType type) { - this.op = op; - this.type = type; - } - - public final void put(Memory mem, long offset, PyObject value) { - op.put(mem, offset, value); - } - - public final PyObject get(Memory mem, long offset) { - PyObject result = type.__call__(op.get(mem, offset)); - // - // Point the CData to the backing memory so all value gets/sets - // update the same memory this pointer points to - // - if (result instanceof CData) { - ((CData) result).setContentMemory(mem); - } - return result; - } - } - } -} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-08-26 05:25:19 UTC (rev 6720) +++ branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-08-26 07:18:30 UTC (rev 6721) @@ -18,7 +18,7 @@ public static void classDictInit(PyObject dict) { dict.__setitem__("__name__", Py.newString("jffi")); dict.__setitem__("DynamicLibrary", DynamicLibrary.TYPE); - dict.__setitem__("Type", Type.TYPE); + dict.__setitem__("Type", CType.TYPE); dict.__setitem__("Pointer", Pointer.TYPE); dict.__setitem__("Function", Function.TYPE); dict.__setitem__("ScalarCData", ScalarCData.TYPE); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-26 05:25:27
|
Revision: 6720 http://jython.svn.sourceforge.net/jython/?rev=6720&view=rev Author: wmeissner Date: 2009-08-26 05:25:19 +0000 (Wed, 26 Aug 2009) Log Message: ----------- Experimental implementation of pointer and byref Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/Type.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/CoreExposed.includes 2009-08-26 05:25:19 UTC (rev 6720) @@ -52,6 +52,7 @@ org/python/modules/_csv/PyWriter.class org/python/modules/_functools/PyPartial.class org/python/modules/_hashlib$Hash.class +org/python/modules/jffi/CData.class org/python/modules/jffi/DynamicLibrary.class org/python/modules/jffi/DynamicLibrary$Symbol.class org/python/modules/jffi/Function.class @@ -59,6 +60,7 @@ org/python/modules/jffi/ScalarCData.class org/python/modules/jffi/Type.class org/python/modules/jffi/Type$Array.class +org/python/modules/jffi/Type$Pointer.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class org/python/modules/_weakref/CallableProxyType.class Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-26 05:25:19 UTC (rev 6720) @@ -32,6 +32,15 @@ def alignment(type): return type._jffi_type.alignment +def byref(cdata): + return cdata.byref() + +def pointer(cdata): + return cdata.pointer() + +def POINTER(type): + return jffi.Type.Pointer(type._jffi_type, type) + class c_byte(_ScalarCData): _jffi_type = jffi.Type.BYTE Added: branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,7 @@ + +package org.python.modules.jffi; + +public interface AllocatedDirectMemory extends DirectMemory { + public void free(); + public void setAutoRelease(boolean autorelease); +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,67 @@ + +package org.python.modules.jffi; + +import org.python.core.Py; + +class AllocatedNativeMemory extends BoundedNativeMemory implements AllocatedDirectMemory { + private volatile boolean released = false; + private volatile boolean autorelease = true; + + /** The real memory address */ + private final long storage; + + /** + * Allocates native memory + * + * @param size The number of bytes to allocate + * @param clear Whether the memory should be cleared (zeroed) + * @return A new {@link AllocatedDirectMemory} + */ + static final AllocatedNativeMemory allocate(int size, boolean clear) { + return allocateAligned(size, 1, clear); + } + + /** + * Allocates native memory, aligned to a minimum boundary. + * + * @param size The number of bytes to allocate + * @param align The minimum alignment of the memory + * @param clear Whether the memory should be cleared (zeroed) + * @return A new {@link AllocatedDirectMemory} + */ + static final AllocatedNativeMemory allocateAligned(int size, int align, boolean clear) { + long memory = IO.allocateMemory(size + align - 1, clear); + if (memory == 0) { + throw Py.RuntimeError("failed to allocate " + size + " bytes"); + } + return new AllocatedNativeMemory(memory, size, align); + } + + private AllocatedNativeMemory(long address, int size, int align) { + super(((address - 1) & ~(align - 1)) + align, size); + this.storage = address; + } + + public void free() { + if (!released) { + IO.freeMemory(storage); + released = true; + } + } + + public void setAutoRelease(boolean release) { + this.autorelease = release; + } + + @Override + protected void finalize() throws Throwable { + try { + if (!released && autorelease) { + IO.freeMemory(storage); + released = true; + } + } finally { + super.finalize(); + } + } +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,80 @@ + +package org.python.modules.jffi; + +import org.python.core.Py; +import org.python.core.PyObject; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedSet; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.CData", base = PyObject.class) +public abstract class CData extends PyObject { + public static final PyType TYPE = PyType.fromClass(CData.class); + + final MemoryOp memoryOp; + final Type type; + + private Memory contentMemory; + private PyObject value; + + CData(PyType subtype, Type type, MemoryOp memoryOp) { + super(subtype); + this.type = type; + this.memoryOp = memoryOp; + this.value = Py.None; + this.contentMemory = null; + } + + @ExposedGet(name = "value") + public PyObject getValue() { + // If native memory has been allocated, read the value from there + if (contentMemory != null) { + return memoryOp.get(contentMemory, 0); + } + + return value; + } + + + @ExposedSet(name = "value") + public void setValue(PyObject value) { + this.value = value; + // If native memory has been allocated, sync the value to memory + if (contentMemory != null) { + memoryOp.put(contentMemory, 0, value); + } + } + + @ExposedMethod(names= { "byref", "pointer" }) + public PyObject byref() { + return new Pointer((DirectMemory) getContentMemory(), memoryOp); + } + + boolean hasValueMemory() { + return contentMemory != null; + } + + void setContentMemory(Memory memory) { + if (!(memory instanceof DirectMemory)) { + throw Py.TypeError("invalid memory"); + } + this.contentMemory = memory; + } + + Memory getContentMemory() { + if (contentMemory != null) { + return contentMemory; + } + + return allocateDirect(); + } + + private DirectMemory allocateDirect() { + DirectMemory m = AllocatedNativeMemory.allocate(type.size(), false); + memoryOp.put(m, 0, value); + contentMemory = m; + return m; + } +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -426,7 +426,11 @@ public static final ParameterMarshaller INSTANCE = new PointerMarshaller(); public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { - throw Py.NotImplementedError("POINTER parameters not implemented"); + if (parameter instanceof Pointer) { + buffer.putAddress(((Pointer) parameter).address); + } else { + throw Py.TypeError("expected pointer argument"); + } } } Added: branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,182 @@ + + +package org.python.modules.jffi; + +import org.python.core.Py; +import org.python.core.PyException; + +/** + * An implementation of Memory that throws an exception on any access. + */ +public abstract class InvalidMemory implements Memory { + private final String message; + + public InvalidMemory(String message) { + this.message = message; + } + + protected PyException ex() { + return Py.MemoryError(message); + } + + public Memory slice(long offset) { + return this; + } + + public java.nio.ByteBuffer asByteBuffer() { + throw ex(); + } + + public final byte getByte(long offset) { + throw ex(); + } + + public final short getShort(long offset) { + throw ex(); + } + + public final int getInt(long offset) { + throw ex(); + } + + public final long getLong(long offset) { + throw ex(); + } + + public final long getNativeLong(long offset) { + throw ex(); + } + + public final float getFloat(long offset) { + throw ex(); + } + + public final double getDouble(long offset) { + throw ex(); + } + + public final DirectMemory getMemory(long offset) { + throw ex(); + } + + public final long getAddress(long offset) { + throw ex(); + } + + public final void putByte(long offset, byte value) { + throw ex(); + } + + public final void putShort(long offset, short value) { + throw ex(); + } + + public final void putInt(long offset, int value) { + throw ex(); + } + + public final void putLong(long offset, long value) { + throw ex(); + } + + public final void putNativeLong(long offset, long value) { + throw ex(); + } + + public final void putFloat(long offset, float value) { + throw ex(); + } + + public final void putDouble(long offset, double value) { + throw ex(); + } + + public final void putMemory(long offset, Memory value) { + throw ex(); + } + + public final void putAddress(long offset, long value) { + throw ex(); + } + + public final void putAddress(long offset, Memory value) { + throw ex(); + } + + public final void get(long offset, byte[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, byte[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, short[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, short[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, int[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, int[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, long[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, long[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, float[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, float[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, double[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, double[] src, int off, int len) { + throw ex(); + } + + public final int indexOf(long offset, byte value) { + throw ex(); + } + + public final int indexOf(long offset, byte value, int maxlen) { + throw ex(); + } + + public final void setMemory(long offset, long size, byte value) { + throw ex(); + } + + public final void clear() { + throw ex(); + } + + public byte[] getZeroTerminatedByteArray(long offset) { + throw ex(); + } + + public byte[] getZeroTerminatedByteArray(long offset, int maxlen) { + throw ex(); + } + + public void putZeroTerminatedByteArray(long offset, byte[] bytes, int off, int len) { + throw ex(); + } + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -8,6 +8,7 @@ * Defines memory operations for a primitive type */ abstract class MemoryOp { + public static final MemoryOp INVALID = new InvalidOp(); public static final MemoryOp VOID = new VoidOp(); public static final MemoryOp INT8 = new Signed8(); public static final MemoryOp UINT8 = new Unsigned8(); @@ -64,6 +65,16 @@ abstract PyObject get(Memory mem, long offset); abstract void put(Memory mem, long offset, PyObject value); + private static final class InvalidOp extends MemoryOp { + public final void put(Memory mem, long offset, PyObject value) { + throw Py.TypeError("invalid memory access"); + } + + public final PyObject get(Memory mem, long offset) { + throw Py.TypeError("invalid memory access"); + } + } + private static final class VoidOp extends MemoryOp { public final void put(Memory mem, long offset, PyObject value) { throw Py.TypeError("Attempting to write void to memory"); @@ -166,11 +177,16 @@ } private static final class PointerOp extends MemoryOp { public final void put(Memory mem, long offset, PyObject value) { - mem.putAddress(offset, Util.int64Value(value)); + if (value instanceof Pointer) { + mem.putAddress(offset, ((Pointer) value).address); + } else { + mem.putAddress(offset, Util.int64Value(value)); + } } public final PyObject get(Memory mem, long offset) { - return Py.newLong(mem.getAddress(offset)); + DirectMemory dm = new NativeMemory(mem.getAddress(offset)); + return new Pointer(dm.getAddress(), dm); } } private static final class StringOp extends MemoryOp { Added: branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,35 @@ + + +package org.python.modules.jffi; + +/** + * An implementation of MemoryIO that throws an exception on any access. + */ +public class NullMemory extends InvalidMemory implements DirectMemory { + static final NullMemory INSTANCE = new NullMemory(); + public NullMemory() { + super("NULL pointer access"); + } + + public long getAddress() { + return 0L; + } + + public boolean isNull() { + return true; + } + public final boolean isDirect() { + return true; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof DirectMemory && ((DirectMemory) obj).getAddress() == 0; + } + + @Override + public int hashCode() { + return 0; + } + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -14,15 +14,35 @@ public final long address; final Memory memory; + final MemoryOp componentMemoryOp; public Pointer(PyType type, long address, Memory memory) { super(type); this.address = address; this.memory = memory; + this.componentMemoryOp = MemoryOp.INVALID; } public Pointer(long address, Memory memory) { this.address = address; this.memory = memory; + this.componentMemoryOp = MemoryOp.INVALID; } + + Pointer(DirectMemory memory, MemoryOp componentMemoryOp) { + this(TYPE, memory, componentMemoryOp); + } + + Pointer(PyType subtype, DirectMemory memory, MemoryOp componentMemoryOp) { + super(subtype); + this.address = memory.getAddress(); + this.memory = memory; + this.componentMemoryOp = componentMemoryOp; + } + + @ExposedGet(name="contents") + public PyObject contents() { + return componentMemoryOp.get(memory, 0); + } + } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -7,21 +7,14 @@ import org.python.core.PyObject; import org.python.core.PyObject.ConversionException; import org.python.core.PyType; -import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; -import org.python.expose.ExposedSet; import org.python.expose.ExposedType; -@ExposedType(name = "jffi.ScalarCData", base = PyObject.class) -public class ScalarCData extends PyObject { +@ExposedType(name = "jffi.ScalarCData", base = CData.class) +public class ScalarCData extends CData { public static final PyType TYPE = PyType.fromClass(ScalarCData.class); - final Type.Builtin type; - private PyObject value; - private Memory memory; - - @ExposedNew public static PyObject ScalarCData_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { @@ -41,31 +34,9 @@ } ScalarCData(PyType pyType, Type.Builtin type) { - super(pyType); - this.type = type; - this.memory = null; - } + super(pyType, type, type.getMemoryOp()); + } - @ExposedGet(name = "value") - public PyObject getValue() { - // If native memory has been allocated, read the value from there - if (memory != null) { - return type.getMemoryOp().get(memory, 0); - } - - return value; - } - - - @ExposedSet(name = "value") - public void setValue(PyObject value) { - this.value = value; - // If native memory has been allocated, sync the value to memory - if (memory != null) { - type.getMemoryOp().put(memory, 0, value); - } - } - @Override public int asInt() { return getValue().asInt(); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Type.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Type.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Type.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -1,20 +1,24 @@ package org.python.modules.jffi; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.python.core.Py; import org.python.core.PyNewWrapper; import org.python.core.PyObject; +import org.python.core.PyObjectDerived; import org.python.core.PyType; import org.python.expose.ExposeAsSuperclass; import org.python.expose.ExposedGet; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; -@ExposedType(name = "jffi.Type", base = PyObject.class) +@ExposedType(name = "jffi.Type", base = PyObjectDerived.class) public class Type extends PyObject { public static final PyType TYPE = PyType.fromClass(Type.class); static { TYPE.fastGetDict().__setitem__("Array", Array.TYPE); + TYPE.fastGetDict().__setitem__("Pointer", Pointer.TYPE); } public static final Type VOID = primitive(NativeType.VOID); public static final Type SINT8 = primitive(NativeType.BYTE); @@ -55,7 +59,6 @@ this.memoryOp = memoryOp; } - public NativeType getNativeType() { return nativeType; } @@ -123,6 +126,104 @@ return length; } + @Override + public final String toString() { + return String.format("<jffi.Type.Array length=%d>", length); + } + } + @ExposedType(name = "jffi.Type.Pointer", base = Type.class) + final static class Pointer extends Type { + public static final PyType TYPE = PyType.fromClass(Pointer.class); + private static final ConcurrentMap<PyObject, Pointer> typeCache + = new ConcurrentHashMap<PyObject, Pointer>(); + + final Type componentType; + final PyType pyComponentType; + final MemoryOp componentMemoryOp; + + Pointer(PyType subtype, Type componentType, PyType pyComponentType) { + super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, MemoryOp.POINTER); + this.componentType = componentType; + this.pyComponentType = pyComponentType; + if (pyComponentType.isSubType(ScalarCData.TYPE)) { + this.componentMemoryOp = new ScalarOp(MemoryOp.getMemoryOp(componentType.getNativeType()), pyComponentType); + } else { + throw Py.TypeError("pointer only supported for scalar types"); + } + + } + + @ExposedNew + public static PyObject Pointer_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + Pointer p = typeCache.get(args[0]); + if (p != null) { + return p; + } + + if (args.length < 1) { + throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); + } + + if (!(args[0] instanceof Type)) { + throw Py.TypeError("expected jffi.Type"); + } + + if (args.length > 1 && !(args[1] instanceof PyType)) { + throw Py.TypeError("expected type"); + } + p = new Pointer(subtype, (Type) args[0], args.length > 1 ? (PyType) args[1] : Py.None.getType()); + typeCache.put(args[0], p); + + return p; + } + + @Override + public final String toString() { + return String.format("<jffi.Type.Pointer component_type=%s>", componentType.toString()); + } + + @Override + public PyObject __call__(PyObject value) { + if (value == Py.None) { + + return new org.python.modules.jffi.Pointer(new NullMemory(), componentMemoryOp); + + } else if (value.getType().isSubType(pyComponentType) && value instanceof CData) { + + return new org.python.modules.jffi.Pointer((DirectMemory) ((CData) value).getContentMemory(), componentMemoryOp); + + } else { + throw Py.TypeError("expected " + pyComponentType.getName() + " instead of " + value.getType().getName()); + } + } + + private static final class ScalarOp extends MemoryOp { + private final MemoryOp op; + private final PyType type; + + public ScalarOp(MemoryOp op, PyType type) { + this.op = op; + this.type = type; + } + + public final void put(Memory mem, long offset, PyObject value) { + op.put(mem, offset, value); + } + + public final PyObject get(Memory mem, long offset) { + PyObject result = type.__call__(op.get(mem, offset)); + // + // Point the CData to the backing memory so all value gets/sets + // update the same memory this pointer points to + // + if (result instanceof CData) { + ((CData) result).setContentMemory(mem); + } + return result; + } + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-08-26 04:19:58
|
Revision: 6719 http://jython.svn.sourceforge.net/jython/?rev=6719&view=rev Author: pjenvey Date: 2009-08-26 04:19:39 +0000 (Wed, 26 Aug 2009) Log Message: ----------- always flush the raw io, even when nothing is buffered Modified Paths: -------------- trunk/jython/src/org/python/core/io/BufferedWriter.java Modified: trunk/jython/src/org/python/core/io/BufferedWriter.java =================================================================== --- trunk/jython/src/org/python/core/io/BufferedWriter.java 2009-08-25 07:59:28 UTC (rev 6718) +++ trunk/jython/src/org/python/core/io/BufferedWriter.java 2009-08-26 04:19:39 UTC (rev 6719) @@ -72,16 +72,13 @@ /** {@inheritDoc} */ public void flush() { - if (buffer.position() == 0) { - // Empty buffer - return; + if (buffer.position() > 0) { + buffer.flip(); + while (buffer.hasRemaining()) { + rawIO.write(buffer); + } + buffer.clear(); } - - buffer.flip(); - while (buffer.hasRemaining()) { - rawIO.write(buffer); - } - buffer.clear(); super.flush(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-25 07:59:36
|
Revision: 6718 http://jython.svn.sourceforge.net/jython/?rev=6718&view=rev Author: cgroves Date: 2009-08-25 07:59:28 +0000 (Tue, 25 Aug 2009) Log Message: ----------- Need to flush the underlying io object after writing our buffer to it to get things really flushed. Fixes issue #1433. Modified Paths: -------------- trunk/jython/src/org/python/core/io/BufferedWriter.java Modified: trunk/jython/src/org/python/core/io/BufferedWriter.java =================================================================== --- trunk/jython/src/org/python/core/io/BufferedWriter.java 2009-08-24 03:30:29 UTC (rev 6717) +++ trunk/jython/src/org/python/core/io/BufferedWriter.java 2009-08-25 07:59:28 UTC (rev 6718) @@ -82,6 +82,7 @@ rawIO.write(buffer); } buffer.clear(); + super.flush(); } /** {@inheritDoc} */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <le...@us...> - 2009-08-24 03:30:36
|
Revision: 6717 http://jython.svn.sourceforge.net/jython/?rev=6717&view=rev Author: leosoto Date: 2009-08-24 03:30:29 +0000 (Mon, 24 Aug 2009) Log Message: ----------- Fixing typo in org.pyton.modules.thread.thread docs Modified Paths: -------------- trunk/jython/src/org/python/modules/thread/thread.java Modified: trunk/jython/src/org/python/modules/thread/thread.java =================================================================== --- trunk/jython/src/org/python/modules/thread/thread.java 2009-08-24 00:10:42 UTC (rev 6716) +++ trunk/jython/src/org/python/modules/thread/thread.java 2009-08-24 03:30:29 UTC (rev 6717) @@ -64,7 +64,7 @@ /** * Interrupts all running threads spawned by the thread module. * - * This works in conjuntion with:<ul> + * This works in conjunction with:<ul> * <li>{@link PyTableCode#call(org.python.core.PyFrame, PyObject)}: * checks for the interrupted status of the current thread and raise * a SystemRestart exception if a interruption is detected.</li> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-24 00:19:54
|
Revision: 6715 http://jython.svn.sourceforge.net/jython/?rev=6715&view=rev Author: wmeissner Date: 2009-08-23 22:47:12 +0000 (Sun, 23 Aug 2009) Log Message: ----------- Add jffi-Darwin.jar to build Modified Paths: -------------- branches/ctypes-jffi/build.xml Modified: branches/ctypes-jffi/build.xml =================================================================== --- branches/ctypes-jffi/build.xml 2009-08-23 22:46:49 UTC (rev 6714) +++ branches/ctypes-jffi/build.xml 2009-08-23 22:47:12 UTC (rev 6715) @@ -193,6 +193,7 @@ <pathelement path="${extlibs.dir}/jna.jar"/> <pathelement path="${extlibs.dir}/jna-posix.jar"/> <pathelement path="${extlibs.dir}/jffi.jar"/> + <pathelement path="${extlibs.dir}/jffi-Darwin.jar"/> <pathelement path="${extlibs.dir}/jffi-i386-SunOS.jar"/> <pathelement path="${extlibs.dir}/jffi-x86_64-SunOS.jar"/> </path> @@ -574,6 +575,7 @@ <rule pattern="org.objectweb.asm.**" result="org.python.objectweb.asm.@1"/> <zipfileset src="extlibs/jna.jar"/> <zipfileset src="extlibs/jffi.jar"/> + <zipfileset src="extlibs/jffi-Darwin.jar"/> <zipfileset src="extlibs/jffi-i386-SunOS.jar"/> <zipfileset src="extlibs/jffi-x86_64-SunOS.jar"/> <zipfileset src="extlibs/jna-posix.jar"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-24 00:11:03
|
Revision: 6716 http://jython.svn.sourceforge.net/jython/?rev=6716&view=rev Author: cgroves Date: 2009-08-24 00:10:42 +0000 (Mon, 24 Aug 2009) Log Message: ----------- Split out visiting and adding a method in a proxy, add a proxy maker that requires all abstract and interface methods be implemented in the Python class, and another overrides all possible superclass methods to allow the Python to method assignment and lookup at runtime. Modified Paths: -------------- branches/customizable-proxymaker/Lib/javaproxymaker.py branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java Modified: branches/customizable-proxymaker/Lib/javaproxymaker.py =================================================================== --- branches/customizable-proxymaker/Lib/javaproxymaker.py 2009-08-23 22:47:12 UTC (rev 6715) +++ branches/customizable-proxymaker/Lib/javaproxymaker.py 2009-08-24 00:10:42 UTC (rev 6716) @@ -1,8 +1,33 @@ +from java.lang.reflect import Modifier from org.python.compiler import JavaMaker as NamedProxyMaker def make_proxynamer(classname): + '''Creates a callable for use in __proxymaker__ that names the generated classes the given name + + If the given name is an invalid Java class name, an exception will be raised at class definition + time.''' def make_proxymaker(superclass, interfaces, pythonClassName, pythonClassDict): proxymaker = NamedProxyMaker(superclass, interfaces, pythonClassName, pythonClassDict) proxymaker.proxyClassName = classname return proxymaker return make_proxymaker + +class StrictProxyMaker(NamedProxyMaker): + '''Requires the Python class implement every abstract or interface Java method. + + If the Python class doesn't have a definition for an abstract or interface method on the class + itself, a TypeError will be raised at class definition time.''' + def visitMethod(self, meth): + if Modifier.isAbstract(meth.modifiers) and not meth.name in self.dict: + raise TypeError("%s must implement %s for %s" % + (self.proxyClassName, meth.name, meth.declaringClass)) + self.super__visitMethod(meth) + +class AllMethodProxyMaker(NamedProxyMaker): + '''Implements every overridable method in the proxy class + + This means that if a Python class doesn't implement a method in its definition, it can still + handle it from __getattribute__ unlike from regular proxy classes. Also, if the overriden + method is abstract and isn't handled by the Python class, a noop return will be performed.''' + def visitMethod(self, meth): + self.addMethod(meth) Modified: branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py =================================================================== --- branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py 2009-08-23 22:47:12 UTC (rev 6715) +++ branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py 2009-08-24 00:10:42 UTC (rev 6716) @@ -8,9 +8,11 @@ from java.lang import Runnable -from javaproxymaker import make_proxynamer, NamedProxyMaker +from org.python.tests import Callbacker -class SettingJavaClassNameTest(unittest.TestCase): +from javaproxymaker import make_proxynamer, AllMethodProxyMaker, NamedProxyMaker, StrictProxyMaker + +class CustomProxyMakerTest(unittest.TestCase): def test_setting_name(self): class Fixedname(Runnable): __proxymaker__ = make_proxynamer('name.set.in.Python') @@ -34,6 +36,35 @@ except TypeError: pass + def test_strict_subclass(self): + try: + class NoRunRunnable(Runnable): + __proxymaker__ = StrictProxyMaker + self.fail("Not implementing Run should throw a TypeError") + except TypeError: + pass + class RunRunnable(Runnable): + __proxymaker__ = StrictProxyMaker + def run(self): + pass + + def test_all_method_subclass(self): + calls = [] + class RuntimeCallbacker(Callbacker.Callback): + __proxymaker__ = AllMethodProxyMaker + + def __getattribute__(self, name): + if name == 'call': + def call(arg=None): + calls.append(arg) + return call + else: + return getattr(self, name) + Callbacker.callNoArg(RuntimeCallbacker()) + self.assertEquals(None, calls[0]) + Callbacker.callOneArg(RuntimeCallbacker(), 12) + self.assertEquals(12, calls[1]) + class StaticProxyCompilationTest(unittest.TestCase): def setUp(self): self.orig_proxy_dir = sys.javaproxy_dir @@ -55,5 +86,4 @@ 0) def test_main(): - test_support.run_unittest(SettingJavaClassNameTest, - StaticProxyCompilationTest) + test_support.run_unittest(CustomProxyMakerTest, StaticProxyCompilationTest) Modified: branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java 2009-08-23 22:47:12 UTC (rev 6715) +++ branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java 2009-08-24 00:10:42 UTC (rev 6716) @@ -16,15 +16,15 @@ @Override protected void build() { classfile.addInterface(mapClass(interfaces[0])); - addMethods(interfaces[0], new HashSet<MethodDescr>()); - addConstructors(); + visitMethods(interfaces[0], new HashSet<MethodDescr>()); + visitConstructors(); for (String name : names) { classfile.addField(name, $pyObj, Opcodes.ACC_PUBLIC); } } @Override - protected void addMethod(Method method, int access) { + protected void addMethod(Method method) { Class<?>[] parameters = method.getParameterTypes(); Class<?> ret = method.getReturnType(); String name = method.getName(); Modified: branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-23 22:47:12 UTC (rev 6715) +++ branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-24 00:10:42 UTC (rev 6716) @@ -69,14 +69,13 @@ } @Override - public void addMethod(Method method, int access) { - if (Modifier.isAbstract(access)) { - // TODO - Allow proxies to determine their handling of missing abstract methods - super.addMethod(method, access); + public void visitMethod(Method method) { + if (Modifier.isAbstract(method.getModifiers())) { + super.visitMethod(method); } else if (dict.__finditem__(method.getName().intern()) != null) { - super.addMethod(method, access); + super.visitMethod(method); } else if (Modifier.isProtected(method.getModifiers())) { - addSuperMethod(method, access); + addSuperMethod(method); } } Modified: branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-23 22:47:12 UTC (rev 6715) +++ branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-24 00:10:42 UTC (rev 6716) @@ -115,10 +115,10 @@ */ protected void build() { addProxy(); - addConstructors(); + visitConstructors(); classfile.addInterface("org/python/core/PyProxy"); - addMethods(); + visitMethods(); addClassDictInit(); } @@ -335,18 +335,13 @@ * <code>method</code> is abstract, the generated method will expect to find an object of the * method's name in the Python object and call it. If it isn't abstract, if an object is found * in the Python object, it'll be called. Otherwise the superclass will be called. - * - * @param modifier - the modifier to be used on the generated method. If the given modifier is - * abstract, that will be removed. */ - protected void addMethod(Method method, int modifier) { - boolean isAbstract = false; - if (Modifier.isAbstract(modifier)) { - modifier = modifier & ~Modifier.ABSTRACT; - isAbstract = true; - } + protected void addMethod(Method method) { + boolean isAbstract = Modifier.isAbstract(method.getModifiers()); + addMethod(method.getName(), method.getReturnType(), method.getParameterTypes(), - method.getExceptionTypes(), modifier, isAbstract ? null : method.getDeclaringClass()); + method.getExceptionTypes(), Modifier.PUBLIC, + isAbstract ? null : method.getDeclaringClass()); } /** @@ -394,7 +389,7 @@ code.label(callPython); code.aload(tmp); callMethod(code, name, parameters, ret, exceptions); - addSuperMethod("super__" + name, name, superClass, parameters, ret, access); + addSuperMethod("super__" + name, name, superClass, parameters, ret); } else { code.invokestatic("org/python/compiler/ProxyMaker", "findPython", makeSig($pyObj, $pyProxy, $str)); @@ -466,8 +461,12 @@ } } - protected void addMethods(Class<?> c, Set<MethodDescr> t) { - for (Method method : c.getDeclaredMethods()) { + /** + * Visits all methods declared on the given class and classes in its inheritance hierarchy. + * Methods visible to subclasses are added to <code>seen</code>. + */ + protected void visitMethods(Class<?> klass, Set<MethodDescr> seen) { + for (Method method : klass.getDeclaredMethods()) { int access = method.getModifiers(); if (Modifier.isStatic(access) || Modifier.isPrivate(access) || @@ -480,38 +479,40 @@ continue; } - if (!t.add(new MethodDescr(method))) { + if (!seen.add(new MethodDescr(method))) { // A method with the same signature has already been added, skip this. continue; } - if (Modifier.isNative(access)) { - access = access & ~Modifier.NATIVE; - } - // TODO - Track accessible final methods in their own Set, protect from overrides - if (Modifier.isProtected(access)) { - access = (access & ~Modifier.PROTECTED) | Modifier.PUBLIC; - if (Modifier.isFinal(access)) { - addSuperMethod(method, access); - continue; + if (Modifier.isFinal(access)) { + if (Modifier.isProtected(access)) { + addSuperMethod(method); } - } else if (Modifier.isFinal(access)) { continue; } - addMethod(method, access); + visitMethod(method); } - Class<?> sc = c.getSuperclass(); - if (sc != null) { - addMethods(sc, t); + Class<?> superClass = klass.getSuperclass(); + if (superClass != null) { + visitMethods(superClass, seen); } - for (Class<?> iface : c.getInterfaces()) { - addMethods(iface, t); + for (Class<?> iface : klass.getInterfaces()) { + visitMethods(iface, seen); } } + /** + * Called for every method on the proxy's superclass and interfaces that can be overriden by the + * proxy class. If the proxy wants to perform Python lookup and calling for the method, + * {@link #addMethod(Method)} should be called. For abstract methods, addMethod must be called. + */ + protected void visitMethod(Method method) { + addMethod(method); + } + /** Adds a constructor that calls through to superclass. */ protected void addConstructor(Class<?>[] parameters, int access) { String sig = makeSig(Void.TYPE, parameters); @@ -520,12 +521,11 @@ } /** - * Adds constructors from this proxy's superclass. + * Visits constructors from this proxy's superclass. */ - protected Set<ConstructorDescr> addConstructors() { + protected Set<ConstructorDescr> visitConstructors() { Set<ConstructorDescr> added = Generic.set(); - Constructor<?>[] constructors = superclass.getDeclaredConstructors(); - for (Constructor<?> constructor : constructors) { + for (Constructor<?> constructor : superclass.getDeclaredConstructors()) { int access = constructor.getModifiers(); if (Modifier.isPrivate(access)) { continue; @@ -556,25 +556,23 @@ // super__ prefix. This gives access to super. version or the // method. // - protected void addSuperMethod(Method method, int access) { + protected void addSuperMethod(Method method) { Class<?>[] parameters = method.getParameterTypes(); Class<?> ret = method.getReturnType(); String superClass = mapClass(method.getDeclaringClass()); String superName = method.getName(); String methodName = superName; - if (Modifier.isFinal(access)) { + if (Modifier.isFinal(method.getModifiers())) { methodName = "super__" + superName; - access &= ~Modifier.FINAL; } - addSuperMethod(methodName, superName, superClass, parameters, ret, access); + addSuperMethod(methodName, superName, superClass, parameters, ret); } protected void addSuperMethod(String methodName, String superName, String declClass, Class<?>[] parameters, - Class<?> ret, - int access) { + Class<?> ret) { if (methodName.startsWith("super__")) { /* rationale: JC java-class, P proxy-class subclassing JC in order to avoid infinite recursion P should define super__foo @@ -592,7 +590,7 @@ } } supernames.add(methodName); - Code code = classfile.addMethod(methodName, makeSig(ret, parameters), access); + Code code = classfile.addMethod(methodName, makeSig(ret, parameters), Modifier.PUBLIC); callSuper(code, superName, declClass, parameters, ret, true); } @@ -645,16 +643,16 @@ code.return_(); } - protected Set<MethodDescr> addMethods() { + protected Set<MethodDescr> visitMethods() { Set<MethodDescr> seenmethods = Generic.set(); - addMethods(superclass, seenmethods); + visitMethods(superclass, seenmethods); for (Class<?> iface : interfaces) { if (iface.isAssignableFrom(superclass)) { Py.writeWarning("compiler", "discarding redundant interface: " + iface.getName()); continue; } classfile.addInterface(mapClass(iface)); - addMethods(iface, seenmethods); + visitMethods(iface, seenmethods); } return seenmethods; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2009-08-23 22:46:59
|
Revision: 6714 http://jython.svn.sourceforge.net/jython/?rev=6714&view=rev Author: thobes Date: 2009-08-23 22:46:49 +0000 (Sun, 23 Aug 2009) Log Message: ----------- Added a bootstrap script that sets up Jython with basic libraries. Also added the beginnings of a benchmarking library with more flexibility than timeit. Modified Paths: -------------- trunk/sandbox/tobias/.classpath trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch trunk/sandbox/tobias/build.xml trunk/sandbox/tobias/tests/parrotbench/b.py Added Paths: ----------- trunk/sandbox/tobias/bootstrap trunk/sandbox/tobias/lib/ trunk/sandbox/tobias/lib/benchmark.py trunk/sandbox/tobias/lib/benchmark.sh Modified: trunk/sandbox/tobias/.classpath =================================================================== --- trunk/sandbox/tobias/.classpath 2009-08-23 19:47:55 UTC (rev 6713) +++ trunk/sandbox/tobias/.classpath 2009-08-23 22:46:49 UTC (rev 6714) @@ -20,7 +20,6 @@ <classpathentry kind="lib" path="jython/extlibs/constantine-0.4.jar"/> <classpathentry kind="lib" path="jython/extlibs/cpptasks/cpptasks.jar"/> <classpathentry kind="lib" path="jython/extlibs/jarjar-0.7.jar"/> - <classpathentry kind="lib" path="jython/extlibs/jline-0.9.94.jar"/> <classpathentry kind="lib" path="jython/extlibs/jna-posix.jar"/> <classpathentry kind="lib" path="jython/extlibs/jna.jar"/> <classpathentry kind="lib" path="jython/extlibs/junit-3.8.2.jar"/> @@ -41,7 +40,9 @@ <classpathentry kind="lib" path="jython/Lib/test/syspath_import.jar"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.5.0 (Mac OS X default)"/> <classpathentry kind="var" path="ANT_HOME/lib/ant.jar"/> - <classpathentry kind="lib" path="jython/extlibs/antlr-3.1.2.jar"/> - <classpathentry kind="lib" path="jython/extlibs/antlr-runtime-3.1.2.jar"/> + <classpathentry kind="lib" path="jython/extlibs/antlr-3.1.3.jar"/> + <classpathentry kind="lib" path="jython/extlibs/antlr-runtime-3.1.3.jar"/> + <classpathentry kind="lib" path="jython/extlibs/jline-0.9.95-SNAPSHOT.jar"/> + <classpathentry kind="lib" path="jython/extlibs/livetribe-jsr223-2.0.5.jar"/> <classpathentry kind="output" path="target/build"/> </classpath> Modified: trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch =================================================================== --- trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch 2009-08-23 19:47:55 UTC (rev 6713) +++ trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch 2009-08-23 22:46:49 UTC (rev 6714) @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="UTF-8"?><launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType"> +<?xml version="1.0" encoding="UTF-8"?> +<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType"> <stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="brand-version,antlr_gen,"/> <stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="brand-version,antlr_gen,"/> <booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/> @@ -18,7 +19,7 @@ <mapEntry key="eclipse.running" value="true"/> <mapEntry key="eclipse.pdebuild.home" value="/Library/eclipse/plugins/org.eclipse.pde.build_3.4.1.R34x_v20080805/./"/> <mapEntry key="eclipse.home" value="/Library/eclipse"/> -<mapEntry key="compile.dir" value="${project_loc}/target/build"/> +<mapEntry key="compile.dir" value="${project_loc:/target/build}"/> <mapEntry key="eclipse.pdebuild.templates" value="/Library/eclipse/plugins/org.eclipse.pde.build_3.4.1.R34x_v20080805/templates/"/> </mapAttribute> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/advanced-compiler/jython/build.xml}"/> Added: trunk/sandbox/tobias/bootstrap =================================================================== --- trunk/sandbox/tobias/bootstrap (rev 0) +++ trunk/sandbox/tobias/bootstrap 2009-08-23 22:46:49 UTC (rev 6714) @@ -0,0 +1,267 @@ +#!/bin/sh + +# <configuration> +# <command names> +CMD_JYTHON=jython +CMD_INSTALL=easy_jython_install +CMD_VIRTUAL=virtualjython +CMD_BENCH=benchmark_jython +# </command names> +# <config files> +CLASSPATH_FILE=~/.jython.classpath +JYTHONPATH_FILE=~/.jython.path +JYTHONOPTIONS_FILE=~/.jython.options +JAVAHOME_FILE=~/.jython.java_home +# </config files> +DEFAULT_INSTALL_PATH=~/bin +BIN_OFFSET=target/dist/bin +EZ_SETUP=http://peak.telecommunity.com/dist/ez_setup.py +BUILD_TARGET= +TEMP_DIR=/tmp +# </configuration> + +install() +{ + if [ -n "$1" ]; then + INSTALL_PATH=$1 + else + echo -n "Enter installation path [$DEFAULT_INSTALL_PATH]: " + read INSTALL_PATH + if [ -z "$INSTALL_PATH" ]; then + INSTALL_PATH=$DEFAULT_INSTALL_PATH + fi + fi + if [ "`dirname ${INSTALL_PATH}x`" != "`dirname $INSTALL_PATH`" ]; then + INSTALL_PATH=`dirname ${INSTALL_PATH}x` + fi + if [ ! -e "$BASE/lib/benchmark.sh" ]; then + CMD_BENCH= + fi + TARGET=$BASE/`basename $EXE` + for SCRIPT in {$CMD_JYTHON,$CMD_INSTALL,$CMD_VIRTUAL,$CMD_BENCH}; do + if ln -is $TARGET $INSTALL_PATH/$SCRIPT; then + echo installed $INSTALL_PATH/$SCRIPT + fi + done +} + +build() +{ + CUR_DIR=`pwd` + cd $BASE + if [ -z "`which ant`" ]; then + echo ERROR: cannot build Jython, could not find ant + exit 1 + fi + echo Rebuilding Jython + ant clean + if [ -n "`which svn`" ]; then + echo Updating working copy + svn up + fi + echo Building Jython + ant $BUILD_TARGET + cd $CUR_DIR +} + +jython() +{ + JYTHON_COMMAND=$BIN_DIR/jython + if [ ! -e "$JYTHON_COMMAND" ]; then + build + elif [ 0 -eq 0 ]; then + # disable the next branch - it is too slow... + echo -n + elif [ -n "`which svn`" ]; then + # TODO: speed up this comparison - then it can be enabled... + BASE_REVISION=`svn info | grep ^Revision` + if [ $? -ne 0 ]; then + echo ERROR: broken working copy + exit 1 + fi + HEAD_REVISION=`svn info -r HEAD | grep ^Revision` + if [ $? -eq 0 ]; then + if [ "$BASE_REVISION" != "$HEAD_REVISION" ]; then + build + fi + fi + fi + if [ -e "$JYTHONOPTIONS_FILE" ]; then + JYTHON_OPTIONS=`lam -s -J $JYTHONOPTIONS_FILE | paste -s -d \ -` + fi + while [ "${1:0:2}" == '-J' ]; do + case "${1:2}" in + # Classpath parameters have arguments + -cp) + JYTHON_OPTIONS="$JYTHON_OPTIONS $1 $2" + shift + ;; + -classpath) + JYTHON_OPTIONS="$JYTHON_OPTIONS $1 $2" + shift + ;; + *) + JYTHON_OPTIONS="$JYTHON_OPTIONS $1" + ;; + esac + shift + done + if [ "$1" == "-m" -a "$2" == "benchmark" ]; then + # benchmarking special case add timing to jython + if [ -e "$BASE/lib/benchmark.sh" ]; then + source $BASE/lib/benchmark.sh + fi + fi + $JYTHON_COMMAND $JYTHON_OPTIONS "$@" + if [ "$1" == "--help" ]; then + echo Bootstrap launcher configuration files: + echo $CLASSPATH_FILE - Configure CLASSPATH, one path per line + echo $JYTHONPATH_FILE - Configure JYTHONPATH, one path per line + echo $JYTHONOPTIONS_FILE - Options passed to the JVM, one per line + fi +} + +benchmark_jython() +{ + for VM in {client,server}; do + echo "=== Benchmarking Jython ($VM VM) ===" + if [ -n "$JAVA_HOME" ]; then + echo " * JAVA_HOME = $JAVA_HOME" + fi + jython -J-$VM -m benchmark "$@" + done +} + +benchmark() +{ + while [ $# -gt 0 ] ; do + case "$1" in + --help) + echo "Run benchmarking of a Python module in CPython and Jython" + echo + echo "Usage:" + echo " $0 <options> <script>.py" + echo "Where <options> can be one or several of the following:" + echo " --jython Run the benchmark in Jython only" + echo " --help Print this message and exit" + exit 0 + ;; + --jython) + JYTHON_ONLY="true" + ;; + *) + break + ;; + esac + shift + done + if [ -z "$1" ]; then + echo "ERROR: No script supplied" + echo "See '$0 --help' for options" + exit 1 + fi + if [ -z "$JYTHON_ONLY" ]; then + echo "=== Benchmarking CPython ===" + time python $BASE/lib/benchmark.py --scripted "$@" + fi + if [ -e "$JAVAHOME_FILE" ]; then + for JAVA_HOME in `cat $JAVAHOME_FILE`; do + export JAVA_HOME + benchmark_jython --scripted "$@" + done + else + benchmark_jython --scripted "$@" + fi +} + +easy_install() +{ + if [ ! -e "$BIN_DIR/easy_install" ]; then + if [ -n "`which wget`" ]; then + wget --output-document=$TEMP_DIR/ez_setup.py $EZ_SETUP + elif [ -n "`which curl`" ]; then + curl -o $TEMP_DIR/ez_setup.py $EZ_SETUP + else + echo ERROR: could not install setuptools + exit 1 + fi + jython $TEMP_DIR/ez_setup.py + rm $TEMP_DIR/ez_setup.py + fi + $BIN_DIR/easy_install "$@" +} + +virtualenv() +{ + if [ ! -e "$BIN_DIR/virtualenv" ]; then + easy_install virtualenv + fi + $BIN_DIR/virtualenv "$@" +} + +NAME=`basename $0` +EXE=$0 +while [ -L "$EXE" ]; do + EXE=`readlink $EXE` +done +BASE=`dirname $EXE` +BASE=`cd $BASE; pwd` +BIN_DIR=$BASE/$BIN_OFFSET + +if [ "$EXE" == "$0" ]; then + install "$@" +else + # Setup CLASSPATH + if [ -e "$CLASSPATH_FILE" ]; then + LOCAL_CLASSPATH=`paste -s -d : $CLASSPATH_FILE` + fi + if [ -n "$CLASSPATH" ]; then + if [ -n "$LOCAL_CLASSPATH" ]; then + export CLASSPATH=$LOCAL_CLASSPATH:$CLASSPATH + fi + else + export CLASSPATH=$LOCAL_CLASSPATH + fi + # Setup JYTHONPATH + if [ -e "$JYTHONPATH_FILE" ]; then + LOCAL_JYTHONPATH=`paste -s -d : $JYTHONPATH_FILE` + fi + if [ -n $"JYTHONPATH" ]; then + if [ -n "$LOCAL_JYTHONPATH" ]; then + export JYTHONPATH=$LOCAL_JYTHONPATH:$BASE/lib:$JYTHONPATH + else + export JYTHONPATH=$BASE/lib:$JYTHONPATH + fi + else + if [ -n "$LOCAL_JYTHONPATH" ]; then + export JYTHONPATH=$LOCAL_JYTHONPATH:$BASE/lib + else + export JYTHONPATH=$BASE/lib + fi + fi + # Setup JAVA_HOME + if [ -z "$JAVA_HOME" ]; then + if [ -e "$JAVAHOME_FILE" ]; then + export JAVA_HOME=`head -n 1 $JAVAHOME_FILE` + fi + fi + # Dispatch command + case "$NAME" in + $CMD_JYTHON) + jython "$@" + ;; + $CMD_INSTALL) + easy_install "$@" + ;; + $CMD_VIRTUAL) + virtualenv "$@" + ;; + $CMD_BENCH) + benchmark "$@" + ;; + *) + echo ERROR: unknown command \"$NAME\" + exit 1 + ;; + esac +fi Property changes on: trunk/sandbox/tobias/bootstrap ___________________________________________________________________ Added: svn:executable + * Modified: trunk/sandbox/tobias/build.xml =================================================================== --- trunk/sandbox/tobias/build.xml 2009-08-23 19:47:55 UTC (rev 6713) +++ trunk/sandbox/tobias/build.xml 2009-08-23 22:46:49 UTC (rev 6714) @@ -53,6 +53,9 @@ </exec> </target> + <target name="source dist"> + </target> + <target name="setup target"> <mkdir dir="${target.dir}"/> </target> Property changes on: trunk/sandbox/tobias/lib ___________________________________________________________________ Added: svn:ignore + *.class *.pyc Added: trunk/sandbox/tobias/lib/benchmark.py =================================================================== --- trunk/sandbox/tobias/lib/benchmark.py (rev 0) +++ trunk/sandbox/tobias/lib/benchmark.py 2009-08-23 22:46:49 UTC (rev 6714) @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Python benchmarking module + +Command line usage: + %(prog)s <module> [<module> ...] +""" + +from __future__ import with_statement + +import sys, traceback + +if __name__ == '__main__': + from benchmark import __main__ + try: + __main__(*sys.argv) + except: + traceback.print_exc() + sys.exit(1) + else: + sys.exit(0) + +__all__ = ('benchmark', 'run') + +def benchmark(*args, **params): + if len(args) > 1: + raise ValueError("Illegal use of benchmark decorator.") + def decorator(func): + func.__benchmark__ = params + return func + if args: + return decorator(*args) + else: + return decorator + +def run(*cases, **params): + if not cases: + if hasattr(sys, '_getframe'): + frame = sys._getframe(1) + while frame and frame.f_globals['__name__'] == __name__: + frame = frame.f_back + if frame: + cases = (frame.f_globals['__name__'],) + benchmarks = [] + for case in cases: + if isstring(case): + if case.endswith('.py'): + env = {'__name__':'__benchmark__', '__file__':case} + try: + with open(case) as file: + exec(file.read(), env) + except: + print("Error in benchmark file '%s'." % (case,)) + traceback.print_exc() + continue + else: + module = _Dummy() + module.__benchmarks__ = env.get('__benchmarks__', ()) + elif case in sys.modules: + module = sys.modules[case] + else: + env = {} + try: + exec("import %s as module" % (case,), env) + except: + print("No such benchmark module '%s'." % (case,)) + continue + else: + module = env['module'] + name = case + for case in getattr(module, '__benchmarks__', ()): + if isstring(case): + try: + benchmarks.append(getattr(module, case)) + except: + print("No such benchmark case '%s' in module '%s'." % + (case, name)) + else: + benchmarks.append((name, case)) + else: + benchmarks.append((None, case)) + _run(benchmarks, params) + +benchmark.run = run + +try: + basestring +except: + def isstring(string): + return isinstance(string, str) +else: + def isstring(string): + return isinstance(string, basestring) + +__DEFAULT__ = object() +class _Dummy(object): pass + +def _run(cases, params): + warmup = params.get('warmup', __DEFAULT__) + if warmup is __DEFAULT__: + pass + elif warmup is None: + pass + else: + pass + for module, case in cases: + name = ('%s.%s' % (module, case.__name__)) if module else case.__name__ + print name + +if sys.platform.lower().startswith('java'): + def _warmup(params): + warmup = params.pop('warmup', None) + if warmup is INTERACTIVE_WARMUP: + pass + elif warmup is not None: + return dict( + iterations=int(warmup), + ) +else: + def _warmup(params): + params.pop('warmup',None) + + +def __main__(script, *args): + from optparse import OptionParser + parser = OptionParser() + parser.add_option('--verbose', action='store_true', default=False) + parser.add_option('--scripted', action='store_true', default=False) + parser.add_option('--runs', type='int', default=1) + parser.add_option('--loops', type='int', default=10) + parser.add_option('--warmup-runs', type='int', default=1) + parser.add_option('--warmup-loops', type='int', default=1) + parser.add_option('--repetitions', '--reps', type='int', default=None) + options, args = parser.parse_args(list(args)) + + params = {'verbose': options.verbose + } + if options.repetitions is not None: + params['repetitions'] = options.repetitions + if not args: + print(__doc__ % {'prog': script}) + else: + run(*args,**params) Added: trunk/sandbox/tobias/lib/benchmark.sh =================================================================== --- trunk/sandbox/tobias/lib/benchmark.sh (rev 0) +++ trunk/sandbox/tobias/lib/benchmark.sh 2009-08-23 22:46:49 UTC (rev 6714) @@ -0,0 +1 @@ +JYTHON_COMMAND="time $JYTHON_COMMAND" Modified: trunk/sandbox/tobias/tests/parrotbench/b.py =================================================================== --- trunk/sandbox/tobias/tests/parrotbench/b.py 2009-08-23 19:47:55 UTC (rev 6713) +++ trunk/sandbox/tobias/tests/parrotbench/b.py 2009-08-23 22:46:49 UTC (rev 6714) @@ -9,7 +9,8 @@ import sys from time import time -WARMUP = 0 +WARMUP = 250 +#WARMUP = 0 TIMES = 3 NUMBER = 1 ITERATIONS = 1 @@ -38,7 +39,7 @@ print >>sys.stderr, "--> iteration", i for module in (b0, b2, b3, b4, b5, b6): # b1 ommitted mt = min(run(module, i)) - print >>sys.stderr, "best of 3:", mt + print >>sys.stderr, "best of %s:" % TIMES, mt t = time() - t print >>sys.stderr, "--> All done.", t This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-23 19:48:03
|
Revision: 6713 http://jython.svn.sourceforge.net/jython/?rev=6713&view=rev Author: cgroves Date: 2009-08-23 19:47:55 +0000 (Sun, 23 Aug 2009) Log Message: ----------- Roll back 6532-6534 and 6548 to keep __javaname__ and sys.javaproxy_dir from going out with 2.5.1. __javaname__ just went away in favor of a naming proxymaker on the customizable-proxymaker branch, and sys.javaproxy_dir doesn't make sense without named proxies. I'll need to re-commit 6533, 6534 and 6548 when I merge customizable-proxymaker to trunk. Modified Paths: -------------- trunk/jython/Lib/test/test_java_subclasses.py trunk/jython/NEWS trunk/jython/src/org/python/compiler/Module.java trunk/jython/src/org/python/core/MakeProxies.java trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/PyType.java trunk/jython/src/org/python/core/util/StringUtil.java trunk/jython/src/org/python/expose/generate/ExposeTask.java trunk/jython/src/org/python/util/GlobMatchingTask.java trunk/jython/src/org/python/util/JycompileAntTask.java Removed Paths: ------------- trunk/jython/Lib/test/import_as_java_class.py trunk/jython/Lib/test/static_proxy.py trunk/jython/src/org/python/util/CompileProxiesTask.java trunk/jython/src/org/python/util/FileNameMatchingTask.java Deleted: trunk/jython/Lib/test/import_as_java_class.py =================================================================== --- trunk/jython/Lib/test/import_as_java_class.py 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/Lib/test/import_as_java_class.py 2009-08-23 19:47:55 UTC (rev 6713) @@ -1,7 +0,0 @@ -# Part of test_java_subclasses.StaticProxyCompilationTest -from java.lang import Class - -# Grab the proxy class statically compiled by the containing test -cls = Class.forName("test.static_proxy.RunnableImpl") -# Instantiating the proxy class should import the module containing it and create the Python side -assert cls.newInstance().meth() == 78 Deleted: trunk/jython/Lib/test/static_proxy.py =================================================================== --- trunk/jython/Lib/test/static_proxy.py 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/Lib/test/static_proxy.py 2009-08-23 19:47:55 UTC (rev 6713) @@ -1,11 +0,0 @@ -# Part of test_java_subclasses.StaticProxyCompilationTest. This needs to be its own module -# so the statically compiled proxy can import it. -from java.lang import Runnable - -class RunnableImpl(Runnable): - __javaname__ = "test.static_proxy.RunnableImpl" - def run(self): - pass - - def meth(self): - return 78 Modified: trunk/jython/Lib/test/test_java_subclasses.py =================================================================== --- trunk/jython/Lib/test/test_java_subclasses.py 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/Lib/test/test_java_subclasses.py 2009-08-23 19:47:55 UTC (rev 6713) @@ -1,8 +1,6 @@ '''Tests subclassing Java classes in Python''' import os import sys -import tempfile -import subprocess import unittest from test import test_support @@ -323,56 +321,10 @@ self.assertEquals(len(called), 1) -class SettingJavaClassNameTest(unittest.TestCase): - def test_setting_name(self): - class Fixedname(Runnable): - __javaname__ = 'name.set.in.Python' - def run(self): - pass - self.assertEquals('name.set.in.Python', Fixedname().getClass().name) - try: - class NumberPackageName(Runnable): - __javaname__ = 'ok.7.ok' - def run(self): - pass - self.fail("Shouldn't be able to set a package name that starts with a digit") - except TypeError: - pass - try: - class LiteralPackageName(Runnable): - __javaname__ = 'ok.true.ok' - def run(self): - pass - self.fail("Shouldn't be able to use a Java literal as a package name") - except TypeError: - pass - -class StaticProxyCompilationTest(unittest.TestCase): - def setUp(self): - self.orig_proxy_dir = sys.javaproxy_dir - sys.javaproxy_dir = tempfile.mkdtemp() - - def tearDown(self): - sys.javaproxy_dir = self.orig_proxy_dir - - def test_proxies_without_classloader(self): - # importing with proxy_dir set compiles RunnableImpl there - import static_proxy - - # Use the existing environment with the proxy dir added on the classpath - env = dict(os.environ) - env["CLASSPATH"] = sys.javaproxy_dir - script = test_support.findfile("import_as_java_class.py") - self.assertEquals(subprocess.call([sys.executable, "-J-Dpython.cachedir.skip=true", - script], env=env), - 0) - def test_main(): test_support.run_unittest(InterfaceTest, TableModelTest, AutoSuperTest, PythonSubclassesTest, AbstractOnSyspathTest, - ContextClassloaderTest, - SettingJavaClassNameTest, - StaticProxyCompilationTest) + ContextClassloaderTest) Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/NEWS 2009-08-23 19:47:55 UTC (rev 6713) @@ -4,8 +4,6 @@ New Features - Upgraded to ANTLR 3.1.3 - [ 1859477 ] Dynamically loaded ServletFilters like PyServlet - - Setting __javaname__ in classes subclassing Java classes or implementing Java interfaces sets - the name of the produced proxy class. - Built in JSR 223 scripting engine, with LiveTribe JSR 223 implementation for JDK 5 - Jython "-J-classpath cp_args_here" now works as expected for unix shell. Bugs Fixed Modified: trunk/jython/src/org/python/compiler/Module.java =================================================================== --- trunk/jython/src/org/python/compiler/Module.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/compiler/Module.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -12,11 +12,6 @@ import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.python.antlr.ParseException; -import org.python.antlr.PythonTree; -import org.python.antlr.ast.Suite; -import org.python.antlr.base.mod; import org.python.core.CodeBootstrap; import org.python.core.CodeFlag; import org.python.core.CodeLoader; @@ -24,7 +19,11 @@ import org.python.core.Py; import org.python.core.PyException; import org.python.core.PyRunnableBootstrap; -import org.python.core.util.StringUtil; +import org.objectweb.asm.Type; +import org.python.antlr.ParseException; +import org.python.antlr.PythonTree; +import org.python.antlr.ast.Suite; +import org.python.antlr.base.mod; class PyIntegerConstant extends Constant implements ClassConstants, Opcodes { @@ -366,7 +365,20 @@ } List<PyCodeConstant> codes; + private boolean isJavaIdentifier(String s) { + char[] chars = s.toCharArray(); + if (chars.length == 0) + return false; + if (!Character.isJavaIdentifierStart(chars[0])) + return false; + for(int i=1; i<chars.length; i++) { + if (!Character.isJavaIdentifierPart(chars[i])) + return false; + } + return true; + } + //XXX: this can probably go away now that we can probably just copy the list. private List<String> toNameAr(List<String> names,boolean nullok) { int sz = names.size(); @@ -411,7 +423,7 @@ code.id = codes.size(); //Better names in the future? - if (StringUtil.isJavaIdentifier(name)) + if (isJavaIdentifier(name)) code.fname = name+"$"+code.id; else code.fname = "f$"+code.id; @@ -537,7 +549,7 @@ c.invokestatic("org/python/core/Py", "runMain", "(" + bootstrap + $strArr + ")V"); c.return_(); } - + public void addBootstrap() throws IOException { Code c = classfile.addMethod(CodeLoader.GET_BOOTSTRAP_METHOD_NAME, "()" + Type.getDescriptor(CodeBootstrap.class), @@ -643,7 +655,7 @@ String name, String filename, boolean linenumbers, boolean printResults, CompilerFlags cflags) - throws Exception + throws Exception { compile(node, ostream, name, filename, linenumbers, printResults, cflags, org.python.core.imp.NO_MTIME); } Modified: trunk/jython/src/org/python/core/MakeProxies.java =================================================================== --- trunk/jython/src/org/python/core/MakeProxies.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/core/MakeProxies.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -8,7 +8,6 @@ import org.python.compiler.AdapterMaker; import org.python.compiler.JavaMaker; -import org.python.core.util.StringUtil; class MakeProxies { @@ -52,28 +51,13 @@ List<Class<?>> vinterfaces, String className, String proxyName, PyObject dict) { Class<?>[] interfaces = vinterfaces.toArray(new Class<?>[vinterfaces.size()]); - String fullProxyName; - PyObject customProxyName = dict.__finditem__("__javaname__"); - if (customProxyName != null) { - fullProxyName = Py.tojava(customProxyName, String.class); - if (!StringUtil.isJavaClassName(fullProxyName)) { - throw Py.TypeError(fullProxyName + " isn't a valid Java class name. Classes " + - "must be valid Java identifiers: " + - "http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#40625"); - } - Class<?> proxy = Py.findClass(fullProxyName); - if (proxy != null) { - return proxy; - } - } else { - fullProxyName = proxyPrefix + proxyName + "$" + proxyNumber++; - } + String fullProxyName = proxyPrefix + proxyName + "$" + proxyNumber++; String pythonModuleName; PyObject mn = dict.__finditem__("__module__"); if (mn == null) { pythonModuleName = "foo"; } else { - pythonModuleName = Py.tojava(mn, String.class); + pythonModuleName = (String) mn.__tojava__(String.class); } JavaMaker jm = new JavaMaker(superclass, interfaces, @@ -84,11 +68,7 @@ try { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); jm.build(bytes); - if (customProxyName != null) { - Py.saveClassFile(fullProxyName, bytes, Py.getSystemState().javaproxy_dir); - } else { - Py.saveClassFile(fullProxyName, bytes); - } + Py.saveClassFile(fullProxyName, bytes); return makeClass(superclass, vinterfaces, jm.myClass, bytes); } catch (Exception exc) { Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/core/Py.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -839,9 +839,8 @@ public static void initProxy(PyProxy proxy, String module, String pyclass, Object[] args) { - if (proxy._getPyInstance() != null) { + if (proxy._getPyInstance() != null) return; - } ThreadState ts = getThreadState(); PyObject instance = ts.getInitializingProxy(); if (instance != null) { @@ -1781,17 +1780,12 @@ } public static void saveClassFile(String name, ByteArrayOutputStream bytestream) { - saveClassFile(name, bytestream, Options.proxyDebugDirectory); - } - - public static void saveClassFile(String name, ByteArrayOutputStream baos, String dirname) { + String dirname = Options.proxyDebugDirectory; if (dirname == null) { return; } - saveClassFile(name, baos.toByteArray(), dirname); - } - public static void saveClassFile(String name, byte[] bytes, String dirname) { + byte[] bytes = bytestream.toByteArray(); File dir = new File(dirname); File file = makeFilename(name, dir); new File(file.getParent()).mkdirs(); Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -186,7 +186,7 @@ underlying_class = forClass; computeLinearMro(baseClass); } else { - needsInners.add(this); + needsInners.add(this); javaProxy = forClass; objtype = PyType.fromClassSkippingInners(Class.class, needsInners); // Wrapped Java types fill in their mro first using all of their interfaces then their Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/core/PySystemState.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -40,7 +40,6 @@ public static final String PYTHON_CACHEDIR_SKIP = "python.cachedir.skip"; public static final String PYTHON_CONSOLE_ENCODING = "python.console.encoding"; protected static final String CACHEDIR_DEFAULT_NAME = "cachedir"; - public static final String PYTHON_JAVAPROXYDIR = "python.javaproxydir"; public static final String JYTHON_JAR = "jython.jar"; public static final String JYTHON_DEV_JAR = "jython-dev.jar"; @@ -139,13 +138,6 @@ public PyObject last_type = Py.None; public PyObject last_traceback = Py.None; - private static String defaultJavaProxyDir; - - /** - * The directory where named Java proxies are written. - */ - public String javaproxy_dir; - public PyObject __name__ = new PyString("sys"); public PyObject __dict__; @@ -197,8 +189,6 @@ __dict__.invoke("update", getType().fastGetDict()); __dict__.__setitem__("displayhook", __displayhook__); __dict__.__setitem__("excepthook", __excepthook__); - - javaproxy_dir = defaultJavaProxyDir; } void reload() throws PyIgnoreMethodTag { @@ -867,8 +857,6 @@ // other initializations initBuiltins(registry); initStaticFields(); - defaultJavaProxyDir = registry.getProperty(PYTHON_JAVAPROXYDIR); - // Initialize the path (and add system defaults) defaultPath = initPath(registry, standalone, jarFileName); defaultArgv = initArgv(argv); Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/core/PyType.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -579,9 +579,11 @@ if (module != null) { proxyName = module.toString() + "$" + proxyName; } - javaProxy = MakeProxies.makeProxy(baseProxyClass, interfaces, name, proxyName, dict); + Class<?> proxyClass = MakeProxies.makeProxy(baseProxyClass, interfaces, name, proxyName, + dict); + javaProxy = proxyClass; - PyType proxyType = PyType.fromClass((Class<?>)javaProxy); + PyType proxyType = PyType.fromClass(proxyClass); List<PyObject> cleanedBases = Generic.list(); boolean addedProxyType = false; for (PyObject base : bases) { Modified: trunk/jython/src/org/python/core/util/StringUtil.java =================================================================== --- trunk/jython/src/org/python/core/util/StringUtil.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/core/util/StringUtil.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -3,10 +3,8 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; -import java.util.Set; import org.python.core.Py; -import org.python.util.Generic; /** * String Utility methods. @@ -86,47 +84,4 @@ chars[0] = Character.toLowerCase(c0); return new String(chars); } - - /** - * Returns true if each segment of <code>name</code> produced by splitting it on '.' is a valid - * Java identifier. - */ - public static boolean isJavaClassName(String name) { - for (String segment : name.split("\\.")) { - if (!isJavaIdentifier(segment)) { - return false; - } - } - return true; - } - - /** - * Returns true if ident is a valid Java identifier as defined by - * http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#40625 - */ - public static boolean isJavaIdentifier(String ident) { - if (ident.length() == 0 || JAVA_LITERALS.contains(ident)) { - return false; - } - int cp = ident.codePointAt(0); - if (!Character.isJavaIdentifierStart(cp)) { - return false; - } - for (int i = Character.charCount(cp); i < ident.length(); i += Character.charCount(cp)) { - cp = ident.codePointAt(i); - if (!Character.isJavaIdentifierPart(cp)) { - return false; - } - } - return true; - } - - // True false and null are just literals, the rest are keywords - private static final Set<String> JAVA_LITERALS = Generic.set("abstract", "continue", "for", - "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", - "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte", - "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", - "class", "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", - "while", "true", "false", "null"); } Modified: trunk/jython/src/org/python/expose/generate/ExposeTask.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposeTask.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/expose/generate/ExposeTask.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -8,8 +8,8 @@ import org.apache.tools.ant.BuildException; import org.objectweb.asm.ClassWriter; +import org.python.core.Py; import org.python.core.Options; -import org.python.core.Py; import org.python.util.GlobMatchingTask; public class ExposeTask extends GlobMatchingTask { Deleted: trunk/jython/src/org/python/util/CompileProxiesTask.java =================================================================== --- trunk/jython/src/org/python/util/CompileProxiesTask.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/util/CompileProxiesTask.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -1,68 +0,0 @@ -package org.python.util; - -import java.io.File; -import java.util.List; -import java.util.Properties; -import java.util.Set; - -import org.apache.tools.ant.BuildException; -import org.python.core.Py; -import org.python.core.PySystemState; - -/** - * Compiles the Java proxies for Python classes in the Python modules in a given directory tree to - * another directory. - */ -public class CompileProxiesTask extends JycompileAntTask { - - @Override - public void process(Set<File> toCompile) throws BuildException { - // Run our superclass' compile first to check that everything has valid syntax before - // attempting to import it and to keep the imports from generating class files in the source - // directory - super.process(toCompile); - Properties props = new Properties(); - props.setProperty(PySystemState.PYTHON_CACHEDIR_SKIP, "true"); - PySystemState.initialize(props, null); - PySystemState sys = Py.getSystemState(); - // Part 2 of not spewing compilation in the source directory: import our compiled files - sys.path.insert(0, Py.newString(destDir.getAbsolutePath())); - sys.javaproxy_dir = destDir.getAbsolutePath(); - PythonInterpreter interp = new PythonInterpreter(); - for (String module : compiledModuleNames) { - try { - interp.exec("import " + module); - } catch (RuntimeException t) { - // We didn't get to import any of these files, so their compiled form can't hang - // around or we won't pick them up as needing compilation next time. - for (File f : compiledModuleFiles) { - f.delete(); - } - throw t; - } - // This module was successfully imported, so its compiled file can hang around - compiledModuleFiles.remove(0); - } - } - - @Override - protected void compile(File src, File compiled, String moduleName) { - try { - super.compile(src, compiled, moduleName); - } catch (BuildException ex) { - // This depends on the modtime of the source being newer than that of the compiled file - // to decide to do the import in process, so even though these files compiled properly, - // they need to be deleted to allow them to be imported in process next time around. - for (File f : compiledModuleFiles) { - f.delete(); - } - throw ex; - } - compiledModuleNames.add(moduleName); - compiledModuleFiles.add(compiled); - } - - private List<String> compiledModuleNames = Generic.list(); - - private List<File> compiledModuleFiles = Generic.list(); -} Deleted: trunk/jython/src/org/python/util/FileNameMatchingTask.java =================================================================== --- trunk/jython/src/org/python/util/FileNameMatchingTask.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/util/FileNameMatchingTask.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -1,95 +0,0 @@ -package org.python.util; - -import java.io.File; -import java.util.Set; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.taskdefs.MatchingTask; -import org.apache.tools.ant.types.Path; -import org.apache.tools.ant.util.FileNameMapper; -import org.apache.tools.ant.util.SourceFileScanner; - -public abstract class FileNameMatchingTask extends MatchingTask { - - private Path src; - - protected File destDir; - - private Set<File> toProcess = Generic.set(); - - /** - * Set the source directories to find the class files to be exposed. - */ - public void setSrcdir(Path srcDir) { - if (src == null) { - src = srcDir; - } else { - src.append(srcDir); - } - } - - /** - * Gets the source dirs to find the class files to be exposed. - */ - public Path getSrcdir() { - return src; - } - - /** - * Set the destination directory into which the Java source files should be compiled. - * - * @param destDir - * the destination director - */ - public void setDestdir(File destDir) { - this.destDir = destDir; - } - - /** - * Gets the destination directory into which the java source files should be compiled. - * - * @return the destination directory - */ - public File getDestdir() { - return destDir; - } - - @Override - public void execute() throws BuildException { - checkParameters(); - toProcess.clear(); - for (String srcEntry : src.list()) { - File srcDir = getProject().resolveFile(srcEntry); - if (!srcDir.exists()) { - throw new BuildException("srcdir '" + srcDir.getPath() + "' does not exist!", - getLocation()); - } - String[] files = getDirectoryScanner(srcDir).getIncludedFiles(); - scanDir(srcDir, destDir != null ? destDir : srcDir, files); - } - process(toProcess); - } - - protected abstract void process(Set<File> matches); - - protected abstract FileNameMapper createMapper(); - - protected void scanDir(File srcDir, File destDir, String[] files) { - SourceFileScanner sfs = new SourceFileScanner(this); - for (File file : sfs.restrictAsFiles(files, srcDir, destDir, createMapper())) { - toProcess.add(file); - } - } - /** - * Check that all required attributes have been set and nothing silly has been entered. - */ - protected void checkParameters() throws BuildException { - if (src == null || src.size() == 0) { - throw new BuildException("srcdir attribute must be set!", getLocation()); - } - if (destDir != null && !destDir.isDirectory()) { - throw new BuildException("destination directory '" + destDir + "' does not exist " - + "or is not a directory", getLocation()); - } - } -} \ No newline at end of file Modified: trunk/jython/src/org/python/util/GlobMatchingTask.java =================================================================== --- trunk/jython/src/org/python/util/GlobMatchingTask.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/util/GlobMatchingTask.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -1,19 +1,101 @@ package org.python.util; -import org.apache.tools.ant.util.FileNameMapper; +import java.io.File; +import java.util.Set; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.MatchingTask; +import org.apache.tools.ant.types.Path; import org.apache.tools.ant.util.GlobPatternMapper; +import org.apache.tools.ant.util.SourceFileScanner; -public abstract class GlobMatchingTask extends FileNameMatchingTask { +public abstract class GlobMatchingTask extends MatchingTask { + private Path src; + + protected File destDir; + + private Set<File> toExpose = Generic.set(); + + /** + * Set the source directories to find the class files to be exposed. + */ + public void setSrcdir(Path srcDir) { + if (src == null) { + src = srcDir; + } else { + src.append(srcDir); + } + } + + /** + * Gets the source dirs to find the class files to be exposed. + */ + public Path getSrcdir() { + return src; + } + + /** + * Set the destination directory into which the Java source files should be compiled. + * + * @param destDir + * the destination director + */ + public void setDestdir(File destDir) { + this.destDir = destDir; + } + + /** + * Gets the destination directory into which the java source files should be compiled. + * + * @return the destination directory + */ + public File getDestdir() { + return destDir; + } + @Override - protected FileNameMapper createMapper() { - FileNameMapper mapper = new GlobPatternMapper(); - mapper.setFrom(getFrom()); - mapper.setTo(getTo()); - return mapper; + public void execute() throws BuildException { + checkParameters(); + toExpose.clear(); + for (String srcEntry : src.list()) { + File srcDir = getProject().resolveFile(srcEntry); + if (!srcDir.exists()) { + throw new BuildException("srcdir '" + srcDir.getPath() + "' does not exist!", + getLocation()); + } + String[] files = getDirectoryScanner(srcDir).getIncludedFiles(); + scanDir(srcDir, destDir != null ? destDir : srcDir, files); + } + process(toExpose); } + protected abstract void process(Set<File> matches); + protected abstract String getFrom(); protected abstract String getTo(); -} + + protected void scanDir(File srcDir, File destDir, String[] files) { + GlobPatternMapper m = new GlobPatternMapper(); + m.setFrom(getFrom()); + m.setTo(getTo()); + SourceFileScanner sfs = new SourceFileScanner(this); + for (File file : sfs.restrictAsFiles(files, srcDir, destDir, m)) { + toExpose.add(file); + } + } + + /** + * Check that all required attributes have been set and nothing silly has been entered. + */ + protected void checkParameters() throws BuildException { + if (src == null || src.size() == 0) { + throw new BuildException("srcdir attribute must be set!", getLocation()); + } + if (destDir != null && !destDir.isDirectory()) { + throw new BuildException("destination directory '" + destDir + "' does not exist " + + "or is not a directory", getLocation()); + } + } +} \ No newline at end of file Modified: trunk/jython/src/org/python/util/JycompileAntTask.java =================================================================== --- trunk/jython/src/org/python/util/JycompileAntTask.java 2009-08-23 19:05:32 UTC (rev 6712) +++ trunk/jython/src/org/python/util/JycompileAntTask.java 2009-08-23 19:47:55 UTC (rev 6713) @@ -59,12 +59,10 @@ imp.cacheCompiledSource(src.getAbsolutePath(), compiled.getAbsolutePath(), bytes); } - @Override protected String getFrom() { return "*.py"; } - @Override protected String getTo() { return "*$py.class"; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-23 19:05:39
|
Revision: 6712 http://jython.svn.sourceforge.net/jython/?rev=6712&view=rev Author: cgroves Date: 2009-08-23 19:05:32 +0000 (Sun, 23 Aug 2009) Log Message: ----------- Kill __javaname__ as a method of setting the classname on generated proxy classes. Instead, add a couple simple proxy makers to a new module, javaproxymaker, that allow proxy classes to be created with a custom proxy name or with the fully qualfied python module + class name. Also, simplify the callable for __proxymaker__ to take Java superclass, Java interfaces, fully qualified Python class name and python class dict. Modified Paths: -------------- branches/customizable-proxymaker/Lib/test/static_proxy.py branches/customizable-proxymaker/Lib/test/test_java_subclasses.py branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java branches/customizable-proxymaker/src/org/python/core/MakeProxies.java Added Paths: ----------- branches/customizable-proxymaker/Lib/javaproxymaker.py branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py Added: branches/customizable-proxymaker/Lib/javaproxymaker.py =================================================================== --- branches/customizable-proxymaker/Lib/javaproxymaker.py (rev 0) +++ branches/customizable-proxymaker/Lib/javaproxymaker.py 2009-08-23 19:05:32 UTC (rev 6712) @@ -0,0 +1,8 @@ +from org.python.compiler import JavaMaker as NamedProxyMaker + +def make_proxynamer(classname): + def make_proxymaker(superclass, interfaces, pythonClassName, pythonClassDict): + proxymaker = NamedProxyMaker(superclass, interfaces, pythonClassName, pythonClassDict) + proxymaker.proxyClassName = classname + return proxymaker + return make_proxymaker Modified: branches/customizable-proxymaker/Lib/test/static_proxy.py =================================================================== --- branches/customizable-proxymaker/Lib/test/static_proxy.py 2009-08-23 18:45:25 UTC (rev 6711) +++ branches/customizable-proxymaker/Lib/test/static_proxy.py 2009-08-23 19:05:32 UTC (rev 6712) @@ -1,9 +1,10 @@ # Part of test_java_subclasses.StaticProxyCompilationTest. This needs to be its own module # so the statically compiled proxy can import it. from java.lang import Runnable +from javaproxymaker import NamedProxyMaker class RunnableImpl(Runnable): - __javaname__ = "test.static_proxy.RunnableImpl" + __proxymaker__ = NamedProxyMaker def run(self): pass Modified: branches/customizable-proxymaker/Lib/test/test_java_subclasses.py =================================================================== --- branches/customizable-proxymaker/Lib/test/test_java_subclasses.py 2009-08-23 18:45:25 UTC (rev 6711) +++ branches/customizable-proxymaker/Lib/test/test_java_subclasses.py 2009-08-23 19:05:32 UTC (rev 6712) @@ -323,56 +323,10 @@ self.assertEquals(len(called), 1) -class SettingJavaClassNameTest(unittest.TestCase): - def test_setting_name(self): - class Fixedname(Runnable): - __javaname__ = 'name.set.in.Python' - def run(self): - pass - self.assertEquals('name.set.in.Python', Fixedname().getClass().name) - try: - class NumberPackageName(Runnable): - __javaname__ = 'ok.7.ok' - def run(self): - pass - self.fail("Shouldn't be able to set a package name that starts with a digit") - except TypeError: - pass - try: - class LiteralPackageName(Runnable): - __javaname__ = 'ok.true.ok' - def run(self): - pass - self.fail("Shouldn't be able to use a Java literal as a package name") - except TypeError: - pass - -class StaticProxyCompilationTest(unittest.TestCase): - def setUp(self): - self.orig_proxy_dir = sys.javaproxy_dir - sys.javaproxy_dir = tempfile.mkdtemp() - - def tearDown(self): - sys.javaproxy_dir = self.orig_proxy_dir - - def test_proxies_without_classloader(self): - # importing with proxy_dir set compiles RunnableImpl there - import static_proxy - - # Use the existing environment with the proxy dir added on the classpath - env = dict(os.environ) - env["CLASSPATH"] = sys.javaproxy_dir - script = test_support.findfile("import_as_java_class.py") - self.assertEquals(subprocess.call([sys.executable, "-J-Dpython.cachedir.skip=true", - script], env=env), - 0) - def test_main(): test_support.run_unittest(InterfaceTest, TableModelTest, AutoSuperTest, PythonSubclassesTest, AbstractOnSyspathTest, - ContextClassloaderTest, - SettingJavaClassNameTest, - StaticProxyCompilationTest) + ContextClassloaderTest) Added: branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py =================================================================== --- branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py (rev 0) +++ branches/customizable-proxymaker/Lib/test/test_javaproxymaker.py 2009-08-23 19:05:32 UTC (rev 6712) @@ -0,0 +1,59 @@ +import os +import subprocess +import sys +import tempfile +import unittest + +from test import test_support + +from java.lang import Runnable + +from javaproxymaker import make_proxynamer, NamedProxyMaker + +class SettingJavaClassNameTest(unittest.TestCase): + def test_setting_name(self): + class Fixedname(Runnable): + __proxymaker__ = make_proxynamer('name.set.in.Python') + def run(self): + pass + self.assertEquals('name.set.in.Python', Fixedname().getClass().name) + try: + class NumberPackageName(Runnable): + __proxymaker__ = make_proxynamer('ok.7.ok') + def run(self): + pass + self.fail("Shouldn't be able to set a package name that starts with a digit") + except TypeError: + pass + try: + class LiteralPackageName(Runnable): + __proxymaker__ = make_proxynamer('ok.true.ok') + def run(self): + pass + self.fail("Shouldn't be able to use a Java literal as a package name") + except TypeError: + pass + +class StaticProxyCompilationTest(unittest.TestCase): + def setUp(self): + self.orig_proxy_dir = sys.javaproxy_dir + sys.javaproxy_dir = tempfile.mkdtemp() + + def tearDown(self): + sys.javaproxy_dir = self.orig_proxy_dir + + def test_proxies_without_classloader(self): + # importing with proxy_dir set compiles RunnableImpl there + import static_proxy + + # Use the existing environment with the proxy dir added on the classpath + env = dict(os.environ) + env["CLASSPATH"] = sys.javaproxy_dir + script = test_support.findfile("import_as_java_class.py") + self.assertEquals(subprocess.call([sys.executable, "-J-Dpython.cachedir.skip=true", + script], env=env), + 0) + +def test_main(): + test_support.run_unittest(SettingJavaClassNameTest, + StaticProxyCompilationTest) Modified: branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-23 18:45:25 UTC (rev 6711) +++ branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-23 19:05:32 UTC (rev 6712) @@ -8,22 +8,26 @@ public class JavaMaker extends ProxyMaker { - public String pythonClass, pythonModule; + public final String pythonClass, pythonModule; - protected PyObject dict; + public PyObject dict; private final boolean proxyNeeded; public JavaMaker(Class<?> superclass, Class<?>[] interfaces, - String pythonClass, - String pythonModule, - String proxyClassName, + String qualifiedPythonClassName, PyObject pythonClassDict) { - super(proxyClassName, superclass, interfaces); + super(qualifiedPythonClassName, superclass, interfaces); proxyNeeded = superclass != null || interfaces.length > 0; - this.pythonClass = pythonClass; - this.pythonModule = pythonModule; + int lastDot = qualifiedPythonClassName.lastIndexOf('.'); + if (lastDot != -1) { + pythonClass = qualifiedPythonClassName.substring(lastDot + 1); + pythonModule = qualifiedPythonClassName.substring(0, lastDot); + } else { + pythonClass = qualifiedPythonClassName; + pythonModule = ""; + } this.dict = pythonClassDict; } @@ -39,7 +43,6 @@ /** * Calls __initProxy__ on this class with the given given types of parameters, which must be * available as arguments to the currently called method in the order of the parameters. - * */ protected void callInitProxy(Class<?>[] parameters, Code code) { code.visitVarInsn(ALOAD, 0); @@ -50,9 +53,7 @@ @Override public void addProxy() { - if (dict != null) { - super.addProxy(); - } + super.addProxy(); // _initProxy method Code code = classfile.addMethod("__initProxy__", makeSig("V", $objArr), Modifier.PUBLIC); Modified: branches/customizable-proxymaker/src/org/python/core/MakeProxies.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/MakeProxies.java 2009-08-23 18:45:25 UTC (rev 6711) +++ branches/customizable-proxymaker/src/org/python/core/MakeProxies.java 2009-08-23 19:05:32 UTC (rev 6712) @@ -24,17 +24,17 @@ List<Class<?>> interfaces, String className, PyObject dict) { - JavaMaker javaMaker = null; - String fullProxyName = null; - String moduleName; + String qualifiedClassName; PyObject module = dict.__finditem__("__module__"); + if (module == null) { - moduleName = "unknown_module"; + qualifiedClassName = className; } else { - moduleName = Py.tojava(module, String.class); + qualifiedClassName = module + "." + className; } Class<?>[] interfacesArr = interfaces.toArray(new Class<?>[interfaces.size()]); + JavaMaker javaMaker; // Grab the proxy maker from the class if it exists, and if it does, use the proxy class // name from the maker PyObject customProxyMaker = dict.__finditem__("__proxymaker__"); @@ -42,52 +42,35 @@ if (module == null) { throw Py.TypeError("Classes using __proxymaker__ must define __module__"); } - PyObject[] args = Py.javas2pys(superclass, interfacesArr, className, moduleName, dict); + PyObject[] args = Py.javas2pys(superclass, interfacesArr, qualifiedClassName, dict); javaMaker = Py.tojava(customProxyMaker.__call__(args), JavaMaker.class); - fullProxyName = javaMaker.proxyClassName; - } - - // Grab the proxy name from the class if it exists, and if it does, override the proxy name - // from the maker if there is one - PyObject customProxyName = dict.__finditem__("__javaname__"); - if (customProxyName != null) { - fullProxyName = Py.tojava(customProxyName, String.class); - if (javaMaker != null) { - javaMaker.proxyClassName = fullProxyName; + if (!StringUtil.isJavaClassName(javaMaker.proxyClassName)) { + throw Py.TypeError(javaMaker.proxyClassName + " isn't a valid Java class name. " + + "Classes must be valid Java identifiers: " + + "http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#40625"); } - } - if (fullProxyName != null) { // If we've gotten a proxy name, check if it's available on the classpath - if (!StringUtil.isJavaClassName(fullProxyName)) { - throw Py.TypeError(fullProxyName + " isn't a valid Java class name. Classes " + - "must be valid Java identifiers: " + - "http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#40625"); - } - Class<?> proxy = Py.findClass(fullProxyName); + Class<?> proxy = Py.findClass(javaMaker.proxyClassName); // TODO - check proxy class version if (proxy != null) { return proxy; } + } else { + javaMaker = new JavaMaker(superclass, interfacesArr, qualifiedClassName, dict); + // This is a purely dynamic proxy + javaMaker.proxyClassName = proxyPrefix + qualifiedClassName + "$" + proxyNumber++; } - if (javaMaker == null) { - if (fullProxyName == null) { - // This is a purely dynamic proxy - fullProxyName = proxyPrefix + moduleName + "$" + className + "$" + proxyNumber++; - } - javaMaker = new JavaMaker(superclass, interfacesArr, className, moduleName, - fullProxyName, dict); - } if (!javaMaker.isProxyNeeded()) { return null; } byte[] bytecode = javaMaker.make(); - if (customProxyName != null || customProxyMaker != null) { - saveBytecode(fullProxyName, bytecode, Py.getSystemState().javaproxy_dir); + if (customProxyMaker != null) { + saveBytecode(javaMaker.proxyClassName, bytecode, Py.getSystemState().javaproxy_dir); } else { - saveDebugBytecode(fullProxyName, bytecode); + saveDebugBytecode(javaMaker.proxyClassName, bytecode); } return makeClass(superclass, interfaces, javaMaker.proxyClassName, bytecode); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-23 18:45:33
|
Revision: 6711 http://jython.svn.sourceforge.net/jython/?rev=6711&view=rev Author: cgroves Date: 2009-08-23 18:45:25 +0000 (Sun, 23 Aug 2009) Log Message: ----------- Allow checked exceptions to be defined on generated methods and pass through checked exceptions for generated proxy methods Modified Paths: -------------- branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java Modified: branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java 2009-08-23 17:35:06 UTC (rev 6710) +++ branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java 2009-08-23 18:45:25 UTC (rev 6711) @@ -74,7 +74,11 @@ } public Code addMethod(String name, String type, int access) { - MethodVisitor mv = cw.visitMethod(access, name, type, null, null); + return addMethod(name, type, access, null); + } + + public Code addMethod(String name, String type, int access, String[] exceptions) { + MethodVisitor mv = cw.visitMethod(access, name, type, null, exceptions); Code pmv = new Code(mv, type, access); methodVisitors.add(pmv); return pmv; Modified: branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java 2009-08-23 17:35:06 UTC (rev 6710) +++ branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java 2009-08-23 18:45:25 UTC (rev 6711) @@ -56,13 +56,21 @@ } } + public static String[] mapClasses(Class<?>[] classes) { + String[] mapped = new String[classes.length]; + for (int i = 0; i < mapped.length; i++) { + mapped[i] = mapClass(classes[i]); + } + return mapped; + } + public static String mapClass(Class<?> c) { String name = c.getName(); int index = name.indexOf("."); if (index == -1) { return name; } - StringBuffer buf = new StringBuffer(name.length()); + StringBuilder buf = new StringBuilder(name.length()); int last_index = 0; while (index != -1) { buf.append(name.substring(last_index, index)); Modified: branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-23 17:35:06 UTC (rev 6710) +++ branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-23 18:45:25 UTC (rev 6711) @@ -377,7 +377,8 @@ int access, Class<?> declaringClass) { names.add(name); - Code code = classfile.addMethod(name, makeSig(ret, parameters), access); + Code code = classfile.addMethod(name, makeSig(ret, parameters), access, + mapClasses(exceptions)); code.aload(0); code.ldc(name); if (declaringClass != null) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-08-23 17:35:16
|
Revision: 6710 http://jython.svn.sourceforge.net/jython/?rev=6710&view=rev Author: fwierzbicki Date: 2009-08-23 17:35:06 +0000 (Sun, 23 Aug 2009) Log Message: ----------- >From CPython http://svn.python.org/python/trunk/Parser/asdl.py@74541 Modified Paths: -------------- trunk/jython/ast/asdl.py Modified: trunk/jython/ast/asdl.py =================================================================== --- trunk/jython/ast/asdl.py 2009-08-22 23:06:08 UTC (rev 6709) +++ trunk/jython/ast/asdl.py 2009-08-23 17:35:06 UTC (rev 6710) @@ -10,14 +10,12 @@ Changes for Python: Add support for module versions """ -#__metaclass__ = type - import os import traceback import spark -class Token: +class Token(object): # spark seems to dispatch in the parser based on a token's # type attribute def __init__(self, type, lineno): @@ -45,7 +43,7 @@ self.value = value self.lineno = lineno -class ASDLSyntaxError: +class ASDLSyntaxError(Exception): def __init__(self, lineno, token=None, msg=None): self.lineno = lineno @@ -167,7 +165,7 @@ return Product(fields) def p_sum_0(self, (constructor,)): - " sum ::= constructor """ + " sum ::= constructor " return [constructor] def p_sum_1(self, (constructor, _, sum)): @@ -206,19 +204,19 @@ def p_field_2(self, (type, _, name)): " field ::= Id * Id " - return Field(type, name, seq=1) + return Field(type, name, seq=True) def p_field_3(self, (type, _, name)): " field ::= Id ? Id " - return Field(type, name, opt=1) + return Field(type, name, opt=True) def p_field_4(self, (type, _)): " field ::= Id * " - return Field(type, seq=1) + return Field(type, seq=True) def p_field_5(self, (type, _)): " field ::= Id ? " - return Field(type, opt=1) + return Field(type, opt=True) builtin_types = ("identifier", "string", "int", "bool", "object") @@ -226,7 +224,7 @@ # not sure if any of the methods are useful yet, but I'm adding them # piecemeal as they seem helpful -class AST: +class AST(object): pass # a marker class class Module(AST): @@ -258,7 +256,7 @@ return "Constructor(%s, %s)" % (self.name, self.fields) class Field(AST): - def __init__(self, type, name=None, seq=0, opt=0): + def __init__(self, type, name=None, seq=False, opt=False): self.type = type self.name = name self.seq = seq @@ -266,9 +264,9 @@ def __repr__(self): if self.seq: - extra = ", seq=1" + extra = ", seq=True" elif self.opt: - extra = ", opt=1" + extra = ", opt=True" else: extra = "" if self.name is None: @@ -296,7 +294,7 @@ class VisitorBase(object): - def __init__(self, skip=0): + def __init__(self, skip=False): self.cache = {} self.skip = skip @@ -331,7 +329,7 @@ class Check(VisitorBase): def __init__(self): - super(Check, self).__init__(skip=1) + super(Check, self).__init__(skip=True) self.cons = {} self.errors = 0 self.types = {} @@ -373,7 +371,7 @@ v.visit(mod) for t in v.types: - if not mod.types.has_key(t) and not t in builtin_types: + if t not in mod.types and not t in builtin_types: v.errors += 1 uses = ", ".join(v.types[t]) print "Undefined type %s, used in %s" % (t, uses) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-23 00:50:27
|
Revision: 6709 http://jython.svn.sourceforge.net/jython/?rev=6709&view=rev Author: cgroves Date: 2009-08-22 23:06:08 +0000 (Sat, 22 Aug 2009) Log Message: ----------- Keep track of added constructors for subclass overriding Modified Paths: -------------- branches/customizable-proxymaker/src/org/python/compiler/Code.java branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java Modified: branches/customizable-proxymaker/src/org/python/compiler/Code.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/Code.java 2009-08-22 23:05:15 UTC (rev 6708) +++ branches/customizable-proxymaker/src/org/python/compiler/Code.java 2009-08-22 23:06:08 UTC (rev 6709) @@ -9,7 +9,7 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -class Code implements MethodVisitor, Opcodes { +public class Code implements MethodVisitor, Opcodes { MethodVisitor mv; String sig; String locals[]; @@ -17,7 +17,7 @@ int argcount; int returnLocal; BitSet finallyLocals = new java.util.BitSet(); - + //XXX: I'd really like to get sig and access out of here since MethodVistitor // should already have this information. public Code(MethodVisitor mv, String sig, int access) { @@ -28,7 +28,7 @@ argcount = nlocals; locals = new String[nlocals+128]; } - + public int getLocal(String type) { //Could optimize this to skip arguments? for(int l = argcount; l<nlocals; l++) { @@ -225,7 +225,7 @@ public void aaload() { mv.visitInsn(AALOAD); } - + public void aastore() { mv.visitInsn(AASTORE); } @@ -293,7 +293,7 @@ public void dup2() { mv.visitInsn(DUP2); } - + public void dup_x1() { mv.visitInsn(DUP_X1); } @@ -313,7 +313,7 @@ public void fconst_0() { mv.visitInsn(FCONST_0); } - + public void fload(int index) { mv.visitVarInsn(FLOAD, index); } @@ -333,7 +333,7 @@ public void goto_(Label label) { mv.visitJumpInsn(GOTO, label); } - + public void iconst(int value) { if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) { switch (value) { @@ -372,31 +372,31 @@ public void iconst_m1() { mv.visitInsn(ICONST_M1); } - + public void iconst_0() { mv.visitInsn(ICONST_0); } - + public void iconst_1() { mv.visitInsn(ICONST_1); } - + public void iconst_2() { mv.visitInsn(ICONST_2); } - + public void iconst_3() { mv.visitInsn(ICONST_3); } - + public void iconst_4() { mv.visitInsn(ICONST_4); } - + public void iconst_5() { mv.visitInsn(ICONST_5); } - + public void ifeq(Label label) { mv.visitJumpInsn(IFEQ, label); } @@ -404,7 +404,7 @@ public void ifle(Label label) { mv.visitJumpInsn(IFLE, label); } - + public void ifne(Label label) { mv.visitJumpInsn(IFNE, label); } @@ -416,31 +416,31 @@ public void ifnonnull(Label label) { mv.visitJumpInsn(IFNONNULL, label); } - + public void if_acmpne(Label label) { mv.visitJumpInsn(IF_ACMPNE, label); } - + public void if_acmpeq(Label label) { mv.visitJumpInsn(IF_ACMPEQ, label); } - + public void if_icmple(Label label) { mv.visitJumpInsn(IF_ICMPLE, label); } - + public void if_icmpgt(Label label) { mv.visitJumpInsn(IF_ICMPGT, label); } - + public void if_icmplt(Label label) { mv.visitJumpInsn(IF_ICMPLT, label); } - + public void if_icmpne(Label label) { mv.visitJumpInsn(IF_ICMPNE, label); } - + public void if_icmpeq(Label label) { mv.visitJumpInsn(IF_ICMPEQ, label); } @@ -476,15 +476,15 @@ public void invokestatic(String owner, String name, String type) { mv.visitMethodInsn(INVOKESTATIC, owner, name, type); } - + public void invokevirtual(String owner, String name, String type) { mv.visitMethodInsn(INVOKEVIRTUAL, owner, name, type); } - + public void ireturn() { mv.visitInsn(IRETURN); } - + public void istore(int index) { mv.visitVarInsn(ISTORE, index); } @@ -506,7 +506,7 @@ String value = (String) cst; final int len = value.length(); // 65535 / 4 (max utf-8 expansion for non BMP characters) - final int maxlen = 16000; + final int maxlen = 16000; if (len > maxlen) { new_("java/lang/StringBuilder"); @@ -553,7 +553,7 @@ public void pop() { mv.visitInsn(POP); } - + public void pop2() { mv.visitInsn(POP2); } @@ -561,11 +561,11 @@ public void putstatic(String owner, String name, String type) { mv.visitFieldInsn(PUTSTATIC, owner, name, type); } - + public void putfield(String owner, String name, String type) { mv.visitFieldInsn(PUTFIELD, owner, name, type); } - + public void ret(int index) { mv.visitVarInsn(RET, index); } @@ -581,7 +581,7 @@ public void swap() { mv.visitInsn(SWAP); } - + public void swap2() { dup2_x2(); pop2(); @@ -594,7 +594,7 @@ public void trycatch(Label start, Label end, Label handlerStart, String type) { mv.visitTryCatchBlock(start, end, handlerStart, type); } - + public void setline(int line) { mv.visitLineNumber(line, new Label()); } Modified: branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-22 23:05:15 UTC (rev 6708) +++ branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-22 23:06:08 UTC (rev 6709) @@ -28,14 +28,11 @@ } @Override - public void addConstructor(String name, - Class<?>[] parameters, - Class<?> ret, - String sig, - int access) { + public void addConstructor(Class<?>[] parameters, int access) { /* Need a fancy constructor for the Java side of things */ + String sig = makeSig(Void.TYPE, parameters); Code code = classfile.addMethod("<init>", sig, access); - callSuper(code, "<init>", name, parameters, null, sig); + callSuper(code, "<init>", mapClass(superclass), parameters, Void.TYPE, false); callInitProxy(parameters, code); } Modified: branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-22 23:05:15 UTC (rev 6708) +++ branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-22 23:06:08 UTC (rev 6709) @@ -126,8 +126,7 @@ String name, String superclass, Class<?>[] parameters, - Class<?> ret, - String sig) { + Class<?> ret, boolean doReturn) { code.aload(0); int local_index; @@ -160,9 +159,11 @@ break; } } - code.invokespecial(superclass, name, sig); + code.invokespecial(superclass, name, makeSig(ret, parameters)); - doReturn(code, ret); + if (doReturn) { + doReturn(code, ret); + } } protected void doJavaCall(Code code, String name, String type, String jcallName) { @@ -376,8 +377,7 @@ int access, Class<?> declaringClass) { names.add(name); - String sig = makeSig(ret, parameters); - Code code = classfile.addMethod(name, sig, access); + Code code = classfile.addMethod(name, makeSig(ret, parameters), access); code.aload(0); code.ldc(name); if (declaringClass != null) { @@ -389,11 +389,11 @@ Label callPython = new Label(); code.ifnonnull(callPython); String superClass = mapClass(declaringClass); - callSuper(code, name, superClass, parameters, ret, sig); + callSuper(code, name, superClass, parameters, ret, true); code.label(callPython); code.aload(tmp); callMethod(code, name, parameters, ret, exceptions); - addSuperMethod("super__" + name, name, superClass, parameters, ret, sig, access); + addSuperMethod("super__" + name, name, superClass, parameters, ret, access); } else { code.invokestatic("org/python/compiler/ProxyMaker", "findPython", makeSig($pyObj, $pyProxy, $str)); @@ -454,6 +454,17 @@ } } + protected static class ConstructorDescr extends MethodDescr { + + public ConstructorDescr(Constructor<?> cons) { + this(cons.getParameterTypes(), cons.getExceptionTypes()); + } + + public ConstructorDescr(Class<?>[] parameters, Class<?>[] exceptions) { + super("<init>", Void.TYPE, parameters, exceptions); + } + } + protected void addMethods(Class<?> c, Set<MethodDescr> t) { for (Method method : c.getDeclaredMethods()) { @@ -501,21 +512,18 @@ } /** Adds a constructor that calls through to superclass. */ - protected void addConstructor(String superclassName, - Class<?>[] parameters, - Class<?> ret, - String sig, - int access) { + protected void addConstructor(Class<?>[] parameters, int access) { + String sig = makeSig(Void.TYPE, parameters); Code code = classfile.addMethod("<init>", sig, access); - callSuper(code, "<init>", superclassName, parameters, Void.TYPE, sig); + callSuper(code, "<init>", mapClass(superclass), parameters, Void.TYPE, true); } /** * Adds constructors from this proxy's superclass. */ - protected void addConstructors() { + protected Set<ConstructorDescr> addConstructors() { + Set<ConstructorDescr> added = Generic.set(); Constructor<?>[] constructors = superclass.getDeclaredConstructors(); - String superclassName = mapClass(superclass); for (Constructor<?> constructor : constructors) { int access = constructor.getModifiers(); if (Modifier.isPrivate(access)) { @@ -527,10 +535,10 @@ if (Modifier.isProtected(access)) { access = access & ~Modifier.PROTECTED | Modifier.PUBLIC; } - Class<?>[] parameters = constructor.getParameterTypes(); - addConstructor(superclassName, parameters, Void.TYPE, makeSig(Void.TYPE, parameters), - access); + addConstructor(constructor.getParameterTypes(), access); + added.add(new ConstructorDescr(constructor)); } + return added; } // Super methods are added for the following three reasons: @@ -557,17 +565,15 @@ methodName = "super__" + superName; access &= ~Modifier.FINAL; } - addSuperMethod(methodName, superName, superClass, parameters, ret, - makeSig(ret, parameters), access); + addSuperMethod(methodName, superName, superClass, parameters, ret, access); } protected void addSuperMethod(String methodName, - String superName, - String declClass, - Class<?>[] parameters, - Class<?> ret, - String sig, - int access) { + String superName, + String declClass, + Class<?>[] parameters, + Class<?> ret, + int access) { if (methodName.startsWith("super__")) { /* rationale: JC java-class, P proxy-class subclassing JC in order to avoid infinite recursion P should define super__foo @@ -585,8 +591,8 @@ } } supernames.add(methodName); - Code code = classfile.addMethod(methodName, sig, access); - callSuper(code, superName, declClass, parameters, ret, sig); + Code code = classfile.addMethod(methodName, makeSig(ret, parameters), access); + callSuper(code, superName, declClass, parameters, ret, true); } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-22 23:05:27
|
Revision: 6708 http://jython.svn.sourceforge.net/jython/?rev=6708&view=rev Author: cgroves Date: 2009-08-22 23:05:15 +0000 (Sat, 22 Aug 2009) Log Message: ----------- Need to go through saveBytecode for the null check Modified Paths: -------------- branches/customizable-proxymaker/src/org/python/core/MakeProxies.java Modified: branches/customizable-proxymaker/src/org/python/core/MakeProxies.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/MakeProxies.java 2009-08-22 20:31:42 UTC (rev 6707) +++ branches/customizable-proxymaker/src/org/python/core/MakeProxies.java 2009-08-22 23:05:15 UTC (rev 6708) @@ -121,7 +121,7 @@ private static void saveDebugBytecode(String className, byte[] bytecode) { @SuppressWarnings("deprecation") String proxyDebugDir = Options.proxyDebugDirectory; - Py.saveClassFile(className, bytecode, proxyDebugDir); + saveBytecode(className, bytecode, proxyDebugDir); } private static final String proxyPrefix = "org.python.proxies."; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-22 20:31:52
|
Revision: 6707 http://jython.svn.sourceforge.net/jython/?rev=6707&view=rev Author: cgroves Date: 2009-08-22 20:31:42 +0000 (Sat, 22 Aug 2009) Log Message: ----------- Allow Python classes to specify the ProxyMaker to use to construct their java proxy by setting __proxymaker__ on the class. The value of __proxymaker__ should be a callable that takes a superclass, iterable of interfaces, name of python class, name of python module and the dict of the class. It needs to return an instance of a subclass of ProxyMaker. Rework ProxyMaker to allow it to be subclassed more easily and hide most of its public fields and methods as protected. Still needs more work in exposing the constructors being added. Deprecate Options.proxyDebugDirectory in favor of sys.javaproxy_dir. Modified Paths: -------------- branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java branches/customizable-proxymaker/src/org/python/core/MakeProxies.java branches/customizable-proxymaker/src/org/python/core/Options.java branches/customizable-proxymaker/src/org/python/core/Py.java branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java branches/customizable-proxymaker/src/org/python/core/PyReflectedFunction.java branches/customizable-proxymaker/src/org/python/core/PyUserType.java Added Paths: ----------- branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java Modified: branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/compiler/AdapterMaker.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -6,7 +6,6 @@ import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; -import org.python.util.Generic; public class AdapterMaker extends ProxyMaker { @@ -15,25 +14,17 @@ } @Override - public void build() throws Exception { - names = Generic.set(); - int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNCHRONIZED; - classfile = new ClassFile(myClass, "java/lang/Object", access); + protected void build() { classfile.addInterface(mapClass(interfaces[0])); - addMethods(interfaces[0], new HashSet<String>()); - addConstructors(Object.class); - doConstants(); - } - - @Override - public void doConstants() throws Exception { + addMethods(interfaces[0], new HashSet<MethodDescr>()); + addConstructors(); for (String name : names) { classfile.addField(name, $pyObj, Opcodes.ACC_PUBLIC); } } @Override - public void addMethod(Method method, int access) throws Exception { + protected void addMethod(Method method, int access) { Class<?>[] parameters = method.getParameterTypes(); Class<?> ret = method.getReturnType(); String name = method.getName(); Modified: branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/compiler/ClassFile.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -29,11 +29,14 @@ List<FieldVisitor> fieldVisitors; public static String fixName(String n) { - if (n.indexOf('.') == -1) + if (n.indexOf('.') == -1) { return n; + } char[] c = n.toCharArray(); - for(int i=0; i<c.length; i++) { - if (c[i] == '.') c[i] = '/'; + for (int i = 0; i < c.length; i++) { + if (c[i] == '.') { + c[i] = '/'; + } } return new String(c); } @@ -46,13 +49,14 @@ public ClassFile(String name, String superclass, int access) { this(name, superclass, access, org.python.core.imp.NO_MTIME); } + public ClassFile(String name, String superclass, int access, long mtime) { this.name = fixName(name); this.superclass = fixName(superclass); this.interfaces = new String[0]; this.access = access; this.mtime = mtime; - + cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); methodVisitors = Collections.synchronizedList(new ArrayList<MethodVisitor>()); fieldVisitors = Collections.synchronizedList(new ArrayList<FieldVisitor>()); @@ -62,49 +66,50 @@ sfilename = name; } - public void addInterface(String name) throws IOException { + public void addInterface(String name) { String[] new_interfaces = new String[interfaces.length+1]; System.arraycopy(interfaces, 0, new_interfaces, 0, interfaces.length); new_interfaces[interfaces.length] = name; interfaces = new_interfaces; } - public Code addMethod(String name, String type, int access) - throws IOException - { + public Code addMethod(String name, String type, int access) { MethodVisitor mv = cw.visitMethod(access, name, type, null, null); Code pmv = new Code(mv, type, access); methodVisitors.add(pmv); return pmv; } - public void addField(String name, String type, int access) - throws IOException - { + public void addField(String name, String type, int access) { FieldVisitor fv = cw.visitField(access, name, type, null, null); fieldVisitors.add(fv); } - public void endFields() - throws IOException - { + public void endFields() { for (FieldVisitor fv : fieldVisitors) { fv.visitEnd(); } } - - public void endMethods() - throws IOException - { - for (int i=0; i<methodVisitors.size(); i++) { + + public void endMethods() { + for (int i = 0; i < methodVisitors.size(); i++) { MethodVisitor mv = methodVisitors.get(i); - mv.visitMaxs(0,0); + mv.visitMaxs(0, 0); mv.visitEnd(); } } public void write(OutputStream stream) throws IOException { - cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, this.name, null, this.superclass, interfaces); + byte[] ba = create(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(ba.length); + baos.write(ba, 0, ba.length); + baos.writeTo(stream); + baos.close(); + } + + public byte[] create() { + cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, this.name, null, + this.superclass, interfaces); AnnotationVisitor av = cw.visitAnnotation("Lorg/python/compiler/APIVersion;", true); // XXX: should imp.java really house this value or should imp.java point into // org.python.compiler? @@ -121,12 +126,6 @@ endFields(); endMethods(); - byte[] ba = cw.toByteArray(); - //fos = io.FileOutputStream("%s.class" % self.name) - ByteArrayOutputStream baos = new ByteArrayOutputStream(ba.length); - baos.write(ba, 0, ba.length); - baos.writeTo(stream); - //debug(baos); - baos.close(); + return cw.toByteArray(); } } Modified: branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/compiler/JavaMaker.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -10,18 +10,21 @@ public String pythonClass, pythonModule; - PyObject methods; + protected PyObject dict; + private final boolean proxyNeeded; + public JavaMaker(Class<?> superclass, Class<?>[] interfaces, String pythonClass, String pythonModule, - String myClass, - PyObject methods) { - super(myClass, superclass, interfaces); + String proxyClassName, + PyObject pythonClassDict) { + super(proxyClassName, superclass, interfaces); + proxyNeeded = superclass != null || interfaces.length > 0; this.pythonClass = pythonClass; this.pythonModule = pythonModule; - this.methods = methods; + this.dict = pythonClassDict; } @Override @@ -29,10 +32,19 @@ Class<?>[] parameters, Class<?> ret, String sig, - int access) throws Exception { + int access) { /* Need a fancy constructor for the Java side of things */ Code code = classfile.addMethod("<init>", sig, access); callSuper(code, "<init>", name, parameters, null, sig); + callInitProxy(parameters, code); + } + + /** + * Calls __initProxy__ on this class with the given given types of parameters, which must be + * available as arguments to the currently called method in the order of the parameters. + * + */ + protected void callInitProxy(Class<?>[] parameters, Code code) { code.visitVarInsn(ALOAD, 0); getArgs(code, parameters); code.visitMethodInsn(INVOKEVIRTUAL, classfile.name, "__initProxy__", makeSig("V", $objArr)); @@ -40,9 +52,10 @@ } @Override - public void addProxy() throws Exception { - if (methods != null) + public void addProxy() { + if (dict != null) { super.addProxy(); + } // _initProxy method Code code = classfile.addMethod("__initProxy__", makeSig("V", $objArr), Modifier.PUBLIC); @@ -58,14 +71,18 @@ } @Override - public void addMethod(Method method, int access) throws Exception { + public void addMethod(Method method, int access) { if (Modifier.isAbstract(access)) { - // Maybe throw an exception here??? + // TODO - Allow proxies to determine their handling of missing abstract methods super.addMethod(method, access); - } else if (methods.__finditem__(method.getName().intern()) != null) { + } else if (dict.__finditem__(method.getName().intern()) != null) { super.addMethod(method, access); } else if (Modifier.isProtected(method.getModifiers())) { addSuperMethod(method, access); } } + + public boolean isProxyNeeded() { + return proxyNeeded; + } } Added: branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java (rev 0) +++ branches/customizable-proxymaker/src/org/python/compiler/ProxyCodeHelpers.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -0,0 +1,182 @@ +package org.python.compiler; + +import java.util.Map; + +import org.python.util.Generic; + +/** + * Various static methods and constants used in generating bytecode for proxy classes. + */ +public class ProxyCodeHelpers { + + public static final int tBoolean = 0; + + public static final int tByte = 1; + + public static final int tShort = 2; + + public static final int tInteger = 3; + + public static final int tLong = 4; + + public static final int tFloat = 5; + + public static final int tDouble = 6; + + public static final int tCharacter = 7; + + public static final int tVoid = 8; + + public static final int tOther = 9; + + public static final int tNone = 10; + + public static Map<Class<?>, Integer> types = Generic.map(); + static { + types.put(Boolean.TYPE, tBoolean); + types.put(Byte.TYPE, tByte); + types.put(Short.TYPE, tShort); + types.put(Integer.TYPE, tInteger); + types.put(Long.TYPE, tLong); + types.put(Float.TYPE, tFloat); + types.put(Double.TYPE, tDouble); + types.put(Character.TYPE, tCharacter); + types.put(Void.TYPE, tVoid); + } + + public static int getType(Class<?> c) { + if (c == null) { + return tNone; + } + Object i = types.get(c); + if (i == null) { + return tOther; + } else { + return ((Integer)i); + } + } + + public static String mapClass(Class<?> c) { + String name = c.getName(); + int index = name.indexOf("."); + if (index == -1) { + return name; + } + StringBuffer buf = new StringBuffer(name.length()); + int last_index = 0; + while (index != -1) { + buf.append(name.substring(last_index, index)); + buf.append("/"); + last_index = index + 1; + index = name.indexOf(".", last_index); + } + buf.append(name.substring(last_index, name.length())); + return buf.toString(); + } + + public static String mapType(Class<?> type) { + if (type.isArray()) + return "[" + mapType(type.getComponentType()); + switch(getType(type)){ + case tByte: + return "B"; + case tCharacter: + return "C"; + case tDouble: + return "D"; + case tFloat: + return "F"; + case tInteger: + return "I"; + case tLong: + return "J"; + case tShort: + return "S"; + case tBoolean: + return "Z"; + case tVoid: + return "V"; + default: + return "L" + mapClass(type) + ";"; + } + } + + public static String makeSig(Class<?> ret, Class<?>... sig) { + String[] mapped = new String[sig.length]; + for (int i = 0; i < mapped.length; i++) { + mapped[i] = mapType(sig[i]); + } + return makeSig(mapType(ret), mapped); + } + + public static String makeSig(String returnType, String... parameterTypes) { + StringBuilder buf = new StringBuilder("("); + for (String param : parameterTypes) { + buf.append(param); + } + return buf.append(')').append(returnType).toString(); + } + + public static void doReturn(Code code, Class<?> type) { + switch(getType(type)){ + case tNone: + break; + case tCharacter: + case tBoolean: + case tByte: + case tShort: + case tInteger: + code.ireturn(); + break; + case tLong: + code.lreturn(); + break; + case tFloat: + code.freturn(); + break; + case tDouble: + code.dreturn(); + break; + case tVoid: + code.return_(); + break; + default: + code.areturn(); + break; + } + } + + public static void doNullReturn(Code code, Class<?> type) { + switch(getType(type)){ + case tNone: + break; + case tCharacter: + case tBoolean: + case tByte: + case tShort: + case tInteger: + code.iconst_0(); + code.ireturn(); + break; + case tLong: + code.lconst_0(); + code.lreturn(); + break; + case tFloat: + code.fconst_0(); + code.freturn(); + break; + case tDouble: + code.dconst_0(); + code.dreturn(); + break; + case tVoid: + code.return_(); + break; + default: + code.aconst_null(); + code.areturn(); + break; + } + } +} Modified: branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/compiler/ProxyMaker.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -1,11 +1,9 @@ // Copyright (c) Corporation for National Research Initiatives package org.python.compiler; -import java.io.OutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.Map; import java.util.Set; import org.objectweb.asm.Label; @@ -17,48 +15,7 @@ import org.python.core.PyReflectedFunction; import org.python.util.Generic; -public class ProxyMaker implements ClassConstants, Opcodes -{ - public static final int tBoolean=0; - public static final int tByte=1; - public static final int tShort=2; - public static final int tInteger=3; - public static final int tLong=4; - public static final int tFloat=5; - public static final int tDouble=6; - public static final int tCharacter=7; - public static final int tVoid=8; - public static final int tOther=9; - public static final int tNone=10; - - public static Map<Class<?>, Integer> types = fillTypes(); - - public static Map<Class<?>, Integer> fillTypes() { - Map<Class<?>, Integer> typeMap = Generic.map(); - typeMap.put(Boolean.TYPE, tBoolean); - typeMap.put(Byte.TYPE, tByte); - typeMap.put(Short.TYPE, tShort); - typeMap.put(Integer.TYPE, tInteger); - typeMap.put(Long.TYPE, tLong); - typeMap.put(Float.TYPE, tFloat); - typeMap.put(Double.TYPE, tDouble); - typeMap.put(Character.TYPE, tCharacter); - typeMap.put(Void.TYPE, tVoid); - return typeMap; - } - - public static int getType(Class<?> c) { - if (c == null) { - return tNone; - } - Object i = types.get(c); - if (i == null) { - return tOther; - } else { - return ((Integer)i); - } - } - +public class ProxyMaker extends ProxyCodeHelpers implements ClassConstants, Opcodes { /** * Retrieves <code>name</code> from the PyObject in <code>proxy</code> if it's defined in * Python. This is a specialized helper function for internal PyProxy use. @@ -86,13 +43,13 @@ return ret; } - Class<?> superclass; - Class<?>[] interfaces; - Set<String> names; - Set<String> supernames = Generic.set(); - public ClassFile classfile; + protected final Class<?> superclass; + protected final Class<?>[] interfaces; + protected final Set<String> names = Generic.set(); + protected final Set<String> supernames = Generic.set(); + protected ClassFile classfile; /** The name of the class to build. */ - public String myClass; + public String proxyClassName; /** * Creates a proxy class maker that produces classes named @@ -100,7 +57,6 @@ * implemented interface or extended class, depending on the its type. * * @deprecated - Use {@link ProxyMaker#ProxyMaker(String, Class, Class[]) - */ @Deprecated public ProxyMaker(String superclassName, Class<?> superclass) { @@ -115,13 +71,15 @@ * extends <code>superclass</code> and implements the interfaces in <code>interfaces</code>. */ public ProxyMaker(String proxyClassName, Class<?> superclass, Class<?>... interfaces) { - this.myClass = proxyClassName; + this.proxyClassName = proxyClassName; if (superclass == null) { superclass = Object.class; } if (superclass.isInterface()) { throw new IllegalArgumentException("Given an interface, " + superclass.getName() + ", for a proxy superclass"); + } else if ((superclass.getModifiers() & Modifier.FINAL) != 0) { + throw new IllegalArgumentException("Can't subclass final class " + superclass.getName()); } this.superclass = superclass; if (interfaces == null) { @@ -137,134 +95,39 @@ this.interfaces = interfaces; } - public static String mapClass(Class<?> c) { - String name = c.getName(); - int index = name.indexOf("."); - if (index == -1) { - return name; - } - StringBuffer buf = new StringBuffer(name.length()); - int last_index = 0; - while (index != -1) { - buf.append(name.substring(last_index, index)); - buf.append("/"); - last_index = index+1; - index = name.indexOf(".", last_index); - } - buf.append(name.substring(last_index, name.length())); - return buf.toString(); + /** + * Builds this proxy and returns its bytecode. + */ + public synchronized byte[] make() { + classfile = new ClassFile(proxyClassName, mapClass(superclass), Modifier.PUBLIC + | Modifier.SYNCHRONIZED); + build(); + names.clear(); + supernames.clear(); + return classfile.create(); } - public static String mapType(Class<?> type) { - if (type.isArray()) - return "["+mapType(type.getComponentType()); + /** + * Called once per created proxy class. Should fill in the necessary methods, constructors and + * interfaces on <code>classfile</code>. Only one call to build will be active at a time, so + * data can be collected in the class as the call proceed, but it should be cleaned up before + * returning to keep later calls to build functioning properly. + */ + protected void build() { + addProxy(); + addConstructors(); + classfile.addInterface("org/python/core/PyProxy"); - switch (getType(type)) { - case tByte: return "B"; - case tCharacter: return "C"; - case tDouble: return "D"; - case tFloat: return "F"; - case tInteger: return "I"; - case tLong: return "J"; - case tShort: return "S"; - case tBoolean: return "Z"; - case tVoid: return "V"; - default: - return "L"+mapClass(type)+";"; - } + addMethods(); + addClassDictInit(); } - public static String makeSig(Class<?> ret, Class<?>... sig) { - String[] mapped = new String[sig.length]; - for (int i = 0; i < mapped.length; i++) { - mapped[i] = mapType(sig[i]); - } - return makeSig(mapType(ret), mapped); - } - - public static String makeSig(String returnType, String... parameterTypes) { - StringBuilder buf = new StringBuilder("("); - for (String param : parameterTypes) { - buf.append(param); - } - return buf.append(')').append(returnType).toString(); - } - - - public void doConstants() throws Exception { - Code code = classfile.addMethod("<clinit>", makeSig("V"), Modifier.STATIC); - code.return_(); - } - - public static void doReturn(Code code, Class<?> type) throws Exception { - switch (getType(type)) { - case tNone: - break; - case tCharacter: - case tBoolean: - case tByte: - case tShort: - case tInteger: - code.ireturn(); - break; - case tLong: - code.lreturn(); - break; - case tFloat: - code.freturn(); - break; - case tDouble: - code.dreturn(); - break; - case tVoid: - code.return_(); - break; - default: - code.areturn(); - break; - } - } - - public static void doNullReturn(Code code, Class<?> type) throws Exception { - switch (getType(type)) { - case tNone: - break; - case tCharacter: - case tBoolean: - case tByte: - case tShort: - case tInteger: - code.iconst_0(); - code.ireturn(); - break; - case tLong: - code.lconst_0(); - code.lreturn(); - break; - case tFloat: - code.fconst_0(); - code.freturn(); - break; - case tDouble: - code.dconst_0(); - code.dreturn(); - break; - case tVoid: - code.return_(); - break; - default: - code.aconst_null(); - code.areturn(); - break; - } - } - - public void callSuper(Code code, + protected void callSuper(Code code, String name, String superclass, Class<?>[] parameters, Class<?> ret, - String sig) throws Exception { + String sig) { code.aload(0); int local_index; @@ -302,16 +165,13 @@ doReturn(code, ret); } - public void doJavaCall(Code code, String name, String type, - String jcallName) - throws Exception - { + protected void doJavaCall(Code code, String name, String type, String jcallName) { code.invokevirtual("org/python/core/PyObject", jcallName, makeSig($pyObj, $objArr)); - code.invokestatic("org/python/core/Py", "py2"+name, makeSig(type, $pyObj)); + code.invokestatic("org/python/core/Py", "py2" + name, makeSig(type, $pyObj)); } - public void getArgs(Code code, Class<?>[] parameters) throws Exception { + protected void getArgs(Code code, Class<?>[] parameters) { if (parameters.length == 0) { code.getstatic("org/python/core/Py", "EmptyObjects", $pyObjArr); } else { @@ -367,11 +227,11 @@ } } - public void callMethod(Code code, - String name, - Class<?>[] parameters, - Class<?> ret, - Class<?>[] exceptions) throws Exception { + protected void callMethod(Code code, + String name, + Class<?>[] parameters, + Class<?> ret, + Class<?>[] exceptions) { Label start = null; Label end = null; @@ -469,79 +329,147 @@ } } - - public void addMethod(Method method, int access) throws Exception { + /** + * Adds an override of <code>method</code> to the class being implemented. If + * <code>method</code> is abstract, the generated method will expect to find an object of the + * method's name in the Python object and call it. If it isn't abstract, if an object is found + * in the Python object, it'll be called. Otherwise the superclass will be called. + * + * @param modifier - the modifier to be used on the generated method. If the given modifier is + * abstract, that will be removed. + */ + protected void addMethod(Method method, int modifier) { boolean isAbstract = false; - - if (Modifier.isAbstract(access)) { - access = access & ~Modifier.ABSTRACT; + if (Modifier.isAbstract(modifier)) { + modifier = modifier & ~Modifier.ABSTRACT; isAbstract = true; } + addMethod(method.getName(), method.getReturnType(), method.getParameterTypes(), + method.getExceptionTypes(), modifier, isAbstract ? null : method.getDeclaringClass()); + } - Class<?>[] parameters = method.getParameterTypes(); - Class<?> ret = method.getReturnType(); - String sig = makeSig(ret, parameters); + /** + * Adds a method to the class being implemented with the given signature. The generated method + * will expect to find an object of the method's name in the Python object and call it. + * + * @param - the modifier to be used on the generated method. + */ + protected void addMethod(String name, + Class<?> ret, + Class<?>[] parameters, + Class<?>[] exceptions, + int modifier) { + addMethod(name, ret, parameters, exceptions, modifier, null); + } - String name = method.getName(); + /** + * Adds a method of the given name to the class being implemented. If + * <code>declaringClass</code> is null, the generated method will expect to find an object of + * the method's name in the Python object and call it. If it isn't null, if an object is found + * in the Python object, it'll be called. Otherwise the superclass will be called. No checking + * is done to guarantee that the superclass has a method with the same signature. + */ + protected void addMethod(String name, + Class<?> ret, + Class<?>[] parameters, + Class<?>[] exceptions, + int access, + Class<?> declaringClass) { names.add(name); - + String sig = makeSig(ret, parameters); Code code = classfile.addMethod(name, sig, access); - code.aload(0); code.ldc(name); - - if (!isAbstract) { + if (declaringClass != null) { int tmp = code.getLocal("org/python/core/PyObject"); code.invokestatic("org/python/compiler/ProxyMaker", "findPython", makeSig($pyObj, $pyProxy, $str)); code.astore(tmp); code.aload(tmp); - Label callPython = new Label(); code.ifnonnull(callPython); - - String superClass = mapClass(method.getDeclaringClass()); - + String superClass = mapClass(declaringClass); callSuper(code, name, superClass, parameters, ret, sig); code.label(callPython); code.aload(tmp); - callMethod(code, name, parameters, ret, method.getExceptionTypes()); - - addSuperMethod("super__"+name, name, superClass, parameters, - ret, sig, access); + callMethod(code, name, parameters, ret, exceptions); + addSuperMethod("super__" + name, name, superClass, parameters, ret, sig, access); } else { code.invokestatic("org/python/compiler/ProxyMaker", "findPython", makeSig($pyObj, $pyProxy, $str)); code.dup(); Label returnNull = new Label(); code.ifnull(returnNull); - callMethod(code, name, parameters, ret, method.getExceptionTypes()); + callMethod(code, name, parameters, ret, exceptions); code.label(returnNull); code.pop(); doNullReturn(code, ret); } } - private String methodString(Method m) { - StringBuffer buf = new StringBuffer(m.getName()); - buf.append(":"); - Class<?>[] params = m.getParameterTypes(); - for (Class<?> param : params) { - buf.append(param.getName()); - buf.append(","); + protected static class MethodDescr { + + public final Class<?> returnType; + + public final String name; + + public final Class<?>[] parameters; + + public final Class<?>[] exceptions; + + public MethodDescr(Method m) { + this(m.getName(), m.getReturnType(), m.getParameterTypes(), m.getExceptionTypes()); } - return buf.toString(); + + public MethodDescr(String name, + Class<?> returnType, + Class<?>[] parameters, + Class<?>[] exceptions) { + this.name = name; + this.returnType = returnType; + this.parameters = parameters; + this.exceptions = exceptions; + } + + @Override + public int hashCode() { + return name.hashCode() + parameters.length; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof MethodDescr)) { + return false; + } + MethodDescr oDescr = (MethodDescr)obj; + if (!name.equals(oDescr.name) || parameters.length != oDescr.parameters.length) { + return false; + } + for (int i = 0; i < parameters.length; i++) { + if (!parameters[i].equals(oDescr.parameters[i])) { + return false; + } + } + return true; + } } - protected void addMethods(Class<?> c, Set<String> t) throws Exception { - Method[] methods = c.getDeclaredMethods(); - for (Method method : methods) { - if (!t.add(methodString(method))) { + protected void addMethods(Class<?> c, Set<MethodDescr> t) { + for (Method method : c.getDeclaredMethods()) { + + int access = method.getModifiers(); + if (Modifier.isStatic(access) || Modifier.isPrivate(access) || + PyReflectedFunction.isPackagedProtected(access)) { + // package protected and private aren't visible to our class, so they don't enter + // into the namespace, and likewise for static methods, regardless of their access. + + // TODO - allow overriding of package protected methods if the generated class is in + // the same package, throw an exception otherwise. continue; } - int access = method.getModifiers(); - if (Modifier.isStatic(access) || Modifier.isPrivate(access)) { + if (!t.add(new MethodDescr(method))) { + // A method with the same signature has already been added, skip this. continue; } @@ -549,6 +477,7 @@ access = access & ~Modifier.NATIVE; } + // TODO - Track accessible final methods in their own Set, protect from overrides if (Modifier.isProtected(access)) { access = (access & ~Modifier.PROTECTED) | Modifier.PUBLIC; if (Modifier.isFinal(access)) { @@ -557,8 +486,6 @@ } } else if (Modifier.isFinal(access)) { continue; - } else if (!Modifier.isPublic(access)) { - continue; // package protected by process of elimination; we can't override } addMethod(method, access); } @@ -573,18 +500,22 @@ } } - public void addConstructor(String name, - Class<?>[] parameters, - Class<?> ret, - String sig, - int access) throws Exception { + /** Adds a constructor that calls through to superclass. */ + protected void addConstructor(String superclassName, + Class<?>[] parameters, + Class<?> ret, + String sig, + int access) { Code code = classfile.addMethod("<init>", sig, access); - callSuper(code, "<init>", name, parameters, Void.TYPE, sig); + callSuper(code, "<init>", superclassName, parameters, Void.TYPE, sig); } - public void addConstructors(Class<?> c) throws Exception { - Constructor<?>[] constructors = c.getDeclaredConstructors(); - String name = mapClass(c); + /** + * Adds constructors from this proxy's superclass. + */ + protected void addConstructors() { + Constructor<?>[] constructors = superclass.getDeclaredConstructors(); + String superclassName = mapClass(superclass); for (Constructor<?> constructor : constructors) { int access = constructor.getModifiers(); if (Modifier.isPrivate(access)) { @@ -597,7 +528,8 @@ access = access & ~Modifier.PROTECTED | Modifier.PUBLIC; } Class<?>[] parameters = constructor.getParameterTypes(); - addConstructor(name, parameters, Void.TYPE, makeSig(Void.TYPE, parameters), access); + addConstructor(superclassName, parameters, Void.TYPE, makeSig(Void.TYPE, parameters), + access); } } @@ -615,7 +547,7 @@ // super__ prefix. This gives access to super. version or the // method. // - public void addSuperMethod(Method method, int access) throws Exception { + protected void addSuperMethod(Method method, int access) { Class<?>[] parameters = method.getParameterTypes(); Class<?> ret = method.getReturnType(); String superClass = mapClass(method.getDeclaringClass()); @@ -625,17 +557,17 @@ methodName = "super__" + superName; access &= ~Modifier.FINAL; } - addSuperMethod(methodName, superName, superClass, parameters, - ret, makeSig(ret, parameters), access); + addSuperMethod(methodName, superName, superClass, parameters, ret, + makeSig(ret, parameters), access); } - public void addSuperMethod(String methodName, + protected void addSuperMethod(String methodName, String superName, String declClass, Class<?>[] parameters, Class<?> ret, String sig, - int access) throws Exception { + int access) { if (methodName.startsWith("super__")) { /* rationale: JC java-class, P proxy-class subclassing JC in order to avoid infinite recursion P should define super__foo @@ -657,45 +589,41 @@ callSuper(code, superName, declClass, parameters, ret, sig); } - public void addProxy() throws Exception { - // implement PyProxy interface + /** + * Adds the methods and fields necessary to implement PyProxy. + */ + protected void addProxy() { classfile.addField("__proxy", $pyObj, Modifier.PROTECTED); - // setProxy methods Code code = classfile.addMethod("_setPyInstance", makeSig("V", $pyObj), Modifier.PUBLIC); code.aload(0); code.aload(1); code.putfield(classfile.name, "__proxy", $pyObj); code.return_(); - // getProxy method code = classfile.addMethod("_getPyInstance", makeSig($pyObj), Modifier.PUBLIC); code.aload(0); code.getfield(classfile.name, "__proxy", $pyObj); code.areturn(); String pySys = "Lorg/python/core/PySystemState;"; - // implement PyProxy interface classfile.addField("__systemState", pySys, Modifier.PROTECTED | Modifier.TRANSIENT); - // setProxy method - code = classfile.addMethod("_setPySystemState", - makeSig("V", pySys), - Modifier.PUBLIC); - + code = classfile.addMethod("_setPySystemState", makeSig("V", pySys), Modifier.PUBLIC); code.aload(0); code.aload(1); code.putfield(classfile.name, "__systemState", pySys); code.return_(); - // getProxy method code = classfile.addMethod("_getPySystemState", makeSig(pySys), Modifier.PUBLIC); code.aload(0); code.getfield(classfile.name, "__systemState", pySys); code.areturn(); } - public void addClassDictInit() throws Exception { - // classDictInit method + /** + * Adds the classDictInit static method to fill in __supernames__ on the class' dict + */ + protected void addClassDictInit() { classfile.addInterface(mapClass(org.python.core.ClassDictInit.class)); Code code = classfile.addMethod("classDictInit", makeSig("V", $pyObj), Modifier.PUBLIC | Modifier.STATIC); @@ -710,28 +638,8 @@ code.return_(); } - /** - * Builds this proxy and writes its bytecode to <code>out</code>. - */ - public void build(OutputStream out) throws Exception { - build(); - classfile.write(out); - } - - public void build() throws Exception { - names = Generic.set(); - int access = superclass.getModifiers(); - if ((access & Modifier.FINAL) != 0) { - throw new InstantiationException("can't subclass final class"); - } - access = Modifier.PUBLIC | Modifier.SYNCHRONIZED; - - classfile = new ClassFile(myClass, mapClass(superclass), access); - addProxy(); - addConstructors(superclass); - classfile.addInterface("org/python/core/PyProxy"); - - Set<String> seenmethods = Generic.set(); + protected Set<MethodDescr> addMethods() { + Set<MethodDescr> seenmethods = Generic.set(); addMethods(superclass, seenmethods); for (Class<?> iface : interfaces) { if (iface.isAssignableFrom(superclass)) { @@ -741,7 +649,6 @@ classfile.addInterface(mapClass(iface)); addMethods(iface, seenmethods); } - doConstants(); - addClassDictInit(); + return seenmethods; } } Modified: branches/customizable-proxymaker/src/org/python/core/MakeProxies.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/MakeProxies.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/core/MakeProxies.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -2,7 +2,6 @@ package org.python.core; -import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; @@ -12,87 +11,120 @@ class MakeProxies { - private static Class<?> makeClass(Class<?> referent, - List<Class<?>> secondary, - String name, - ByteArrayOutputStream bytes) { - List<Class<?>> referents = null; - if (secondary != null) { - if (referent != null) { - secondary.add(0, referent); - } - referents = secondary; - } else if (referent != null) { - referents = new ArrayList<Class<?>>(1); - referents.add(referent); - } - - return BytecodeLoader.makeClass(name, referents, bytes.toByteArray()); - } - public static Class<?> makeAdapter(Class<?> c) { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); AdapterMaker maker = new AdapterMaker(proxyPrefix + c.getName(), c); - try { - maker.build(bytes); - } catch (Exception exc) { - throw Py.JavaError(exc); - } + byte[] bytecode = maker.make(); - Py.saveClassFile(maker.myClass, bytes); + saveDebugBytecode(maker.proxyClassName, bytecode); - return makeClass(c, null, maker.myClass, bytes); + return makeClass(c, null, maker.proxyClassName, bytecode); } - private static final String proxyPrefix = "org.python.proxies."; + public static synchronized Class<?> makeProxy(Class<?> superclass, + List<Class<?>> interfaces, + String className, + PyObject dict) { + JavaMaker javaMaker = null; + String fullProxyName = null; + String moduleName; + PyObject module = dict.__finditem__("__module__"); + if (module == null) { + moduleName = "unknown_module"; + } else { + moduleName = Py.tojava(module, String.class); + } + Class<?>[] interfacesArr = interfaces.toArray(new Class<?>[interfaces.size()]); - private static int proxyNumber = 0; + // Grab the proxy maker from the class if it exists, and if it does, use the proxy class + // name from the maker + PyObject customProxyMaker = dict.__finditem__("__proxymaker__"); + if (customProxyMaker != null) { + if (module == null) { + throw Py.TypeError("Classes using __proxymaker__ must define __module__"); + } + PyObject[] args = Py.javas2pys(superclass, interfacesArr, className, moduleName, dict); + javaMaker = Py.tojava(customProxyMaker.__call__(args), JavaMaker.class); + fullProxyName = javaMaker.proxyClassName; + } - public static synchronized Class<?> makeProxy(Class<?> superclass, - List<Class<?>> vinterfaces, String className, String proxyName, - PyObject dict) { - Class<?>[] interfaces = vinterfaces.toArray(new Class<?>[vinterfaces.size()]); - String fullProxyName; + // Grab the proxy name from the class if it exists, and if it does, override the proxy name + // from the maker if there is one PyObject customProxyName = dict.__finditem__("__javaname__"); if (customProxyName != null) { fullProxyName = Py.tojava(customProxyName, String.class); + if (javaMaker != null) { + javaMaker.proxyClassName = fullProxyName; + } + } + + if (fullProxyName != null) { + // If we've gotten a proxy name, check if it's available on the classpath if (!StringUtil.isJavaClassName(fullProxyName)) { throw Py.TypeError(fullProxyName + " isn't a valid Java class name. Classes " + "must be valid Java identifiers: " + "http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#40625"); } Class<?> proxy = Py.findClass(fullProxyName); + + // TODO - check proxy class version if (proxy != null) { return proxy; } - } else { - fullProxyName = proxyPrefix + proxyName + "$" + proxyNumber++; } - String pythonModuleName; - PyObject mn = dict.__finditem__("__module__"); - if (mn == null) { - pythonModuleName = "foo"; + if (javaMaker == null) { + if (fullProxyName == null) { + // This is a purely dynamic proxy + fullProxyName = proxyPrefix + moduleName + "$" + className + "$" + proxyNumber++; + } + javaMaker = new JavaMaker(superclass, interfacesArr, className, moduleName, + fullProxyName, dict); + } + if (!javaMaker.isProxyNeeded()) { + return null; + } + + byte[] bytecode = javaMaker.make(); + if (customProxyName != null || customProxyMaker != null) { + saveBytecode(fullProxyName, bytecode, Py.getSystemState().javaproxy_dir); } else { - pythonModuleName = Py.tojava(mn, String.class); + saveDebugBytecode(fullProxyName, bytecode); } - JavaMaker jm = new JavaMaker(superclass, - interfaces, - className, - pythonModuleName, - fullProxyName, - dict); - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - jm.build(bytes); - if (customProxyName != null) { - Py.saveClassFile(fullProxyName, bytes, Py.getSystemState().javaproxy_dir); - } else { - Py.saveClassFile(fullProxyName, bytes); + return makeClass(superclass, interfaces, javaMaker.proxyClassName, bytecode); + } + + private static Class<?> makeClass(Class<?> referent, + List<Class<?>> secondary, + String name, + byte[] bytes) { + List<Class<?>> referents = null; + if (secondary != null) { + if (referent != null) { + secondary.add(0, referent); } + referents = secondary; + } else if (referent != null) { + referents = new ArrayList<Class<?>>(1); + referents.add(referent); + } + return BytecodeLoader.makeClass(name, referents, bytes); + } - return makeClass(superclass, vinterfaces, jm.myClass, bytes); - } catch (Exception exc) { - throw Py.JavaError(exc); + /** Writes the bytecode to the given directory if it's non-null. */ + private static void saveBytecode(String className, byte[] bytecode, String directory) { + if (directory == null) { + return; } + Py.saveClassFile(className, bytecode, directory); } + + /** Writes the bytecode to {@link Options#proxyDebugDirectory} if it's non-null. */ + private static void saveDebugBytecode(String className, byte[] bytecode) { + @SuppressWarnings("deprecation") + String proxyDebugDir = Options.proxyDebugDirectory; + Py.saveClassFile(className, bytecode, proxyDebugDir); + } + + private static final String proxyPrefix = "org.python.proxies."; + + private static int proxyNumber = 0; } Modified: branches/customizable-proxymaker/src/org/python/core/Options.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/Options.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/core/Options.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -54,8 +54,11 @@ public static int verbose = Py.MESSAGE; /** - * A directory where the dynamically generated classes are written. Nothing is - * ever read from here, it is only for debugging purposes. + * A directory where the dynamically generated classes are written. Nothing is ever read from + * here, it is only for debugging purposes. + * + * @deprecated - Give the proxy a __javaname__ and use {@link PySystemState#javaproxy_dir} + * instead. */ public static String proxyDebugDirectory; Modified: branches/customizable-proxymaker/src/org/python/core/Py.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/Py.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/core/Py.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -1780,10 +1780,24 @@ maybeWrite(type, msg, DEBUG); } + /** + * Writes a class with the given name contained in the given output stream to + * {@link Options#proxyDebugDirectory} if it's set. + * + * @deprecated {@link Options#proxyDebugDirectory} is deprecated. Use + * {@link #saveClassFile(String, ByteArrayOutputStream, String)} directly instead. + */ public static void saveClassFile(String name, ByteArrayOutputStream bytestream) { saveClassFile(name, bytestream, Options.proxyDebugDirectory); } + /** + * Writes a class with the given name contained in the given output stream to the given + * directory, if it's non-null. + * + * @deprecated Use {@link #saveClassFile(String, ByteArrayOutputStream, String)} directly + * instead. + */ public static void saveClassFile(String name, ByteArrayOutputStream baos, String dirname) { if (dirname == null) { return; @@ -1791,6 +1805,9 @@ saveClassFile(name, baos.toByteArray(), dirname); } + /** + * Writes a class with the given name consisting of the given bytes to the given directory. + */ public static void saveClassFile(String name, byte[] bytes, String dirname) { File dir = new File(dirname); File file = makeFilename(name, dir); Modified: branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -17,7 +17,7 @@ /** Mapping of Java classes to their TypeBuilders. */ private static Map<Class<?>, TypeBuilder> classToBuilder; - PyBuiltinType(PyType pyType) { + protected PyBuiltinType(PyType pyType) { super(pyType); } Modified: branches/customizable-proxymaker/src/org/python/core/PyReflectedFunction.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyReflectedFunction.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/core/PyReflectedFunction.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -113,7 +113,10 @@ } public static boolean isPackagedProtected(Class<?> c) { - int mods = c.getModifiers(); + return isPackagedProtected(c.getModifiers()); + } + + public static boolean isPackagedProtected(int mods) { return !(Modifier.isPublic(mods) || Modifier.isPrivate(mods) || Modifier.isProtected(mods)); } Modified: branches/customizable-proxymaker/src/org/python/core/PyUserType.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyUserType.java 2009-08-22 20:23:25 UTC (rev 6706) +++ branches/customizable-proxymaker/src/org/python/core/PyUserType.java 2009-08-22 20:31:42 UTC (rev 6707) @@ -9,7 +9,7 @@ public class PyUserType extends PyType implements ExposeAsSuperclass { - protected PyUserType(PyType metatype, String name, PyTuple bases, PyObject dict) { + public PyUserType(PyType metatype, String name, PyTuple bases, PyObject dict) { super(metatype); this.name = name; this.bases = bases.isEmpty() ? new PyObject[] {PyObject.TYPE} : bases.getArray(); @@ -46,31 +46,11 @@ protected void setupProxy() { List<Class<?>> interfaces = Generic.list(); Class<?> baseProxyClass = getJavaLayout(this.bases, interfaces); - setupProxy(baseProxyClass, interfaces); - } - - /** - * Setup the javaProxy for this type. If baseProxyClass is null and interfaces is empty, no - * proxy class will be created or assigned. - * - * @param baseProxyClass - * this type's base proxyClass or null if there is no base class - * @param interfaces - * a list of Java interfaces this type should implement - */ - protected void setupProxy(Class<?> baseProxyClass, List<Class<?>> interfaces) { - if (baseProxyClass == null && interfaces.isEmpty()) { - // javaProxy not applicable + javaProxy = MakeProxies.makeProxy(baseProxyClass, interfaces, name, dict); + if (javaProxy == null) { return; } - String proxyName = name; - PyObject module = dict.__finditem__("__module__"); - if (module != null) { - proxyName = module.toString() + "$" + proxyName; - } - javaProxy = MakeProxies.makeProxy(baseProxyClass, interfaces, name, proxyName, dict); - PyType proxyType = PyType.fromClass((Class<?>)javaProxy); List<PyObject> cleanedBases = Generic.list(); boolean addedProxyType = false; @@ -97,6 +77,9 @@ } } } + if (!addedProxyType) { + cleanedBases.add(proxyType); + } bases = cleanedBases.toArray(new PyObject[cleanedBases.size()]); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-22 20:23:34
|
Revision: 6706 http://jython.svn.sourceforge.net/jython/?rev=6706&view=rev Author: cgroves Date: 2009-08-22 20:23:25 +0000 (Sat, 22 Aug 2009) Log Message: ----------- Cleanup Modified Paths: -------------- branches/customizable-proxymaker/src/org/python/compiler/CodeCompiler.java branches/customizable-proxymaker/src/org/python/util/jython.java Modified: branches/customizable-proxymaker/src/org/python/compiler/CodeCompiler.java =================================================================== --- branches/customizable-proxymaker/src/org/python/compiler/CodeCompiler.java 2009-08-22 10:50:40 UTC (rev 6705) +++ branches/customizable-proxymaker/src/org/python/compiler/CodeCompiler.java 2009-08-22 20:23:25 UTC (rev 6706) @@ -137,7 +137,7 @@ public int bcfLevel = 0; int yield_count = 0; - + private Stack<String> stack = new Stack<String>(); public CodeCompiler(Module module, boolean print_results) { @@ -169,7 +169,7 @@ code.iconst(idx); code.putfield("org/python/core/PyFrame", "f_lasti", "I"); } - + private void loadf_back() throws Exception { code.getfield("org/python/core/PyFrame", "f_back", $pyFrame); } @@ -264,7 +264,7 @@ tbl = scope.tbl; optimizeGlobals = fast_locals&&!scope.exec&&!scope.from_import_star; - + if (scope.max_with_count > 0) { // allocate for all the with-exits we will have in the frame; // this allows yield and with to happily co-exist @@ -432,7 +432,7 @@ } else { code.invokespecial( "org/python/core/PyFunction", "<init>", "(" + $pyObj + $pyObjArr + $pyCode + $pyObj + $pyObjArr + ")V"); } - + applyDecorators(node.getInternalDecorator_list()); set(new Name(node,node.getInternalName(), expr_contextType.Store)); @@ -576,15 +576,15 @@ } int stackState = saveStack(); - + if (node.getInternalValue() != null) { visit(node.getInternalValue()); } else { getNone(); } - + setLastI(++yield_count); - + saveLocals(); code.areturn(); @@ -593,7 +593,7 @@ code.label(restart); restoreLocals(); restoreStack(stackState); - + loadFrame(); code.invokevirtual("org/python/core/PyFrame", "getGeneratorInput", "()" + $obj); code.dup(); @@ -604,14 +604,14 @@ code.athrow(); code.label(done2); code.checkcast("org/python/core/PyObject"); - + return null; } - + private void stackProduce() { stackProduce("org/python/core/PyObject"); } - + private void stackProduce(String signature) { stack.push(signature); } @@ -619,7 +619,7 @@ private void stackConsume() { stackConsume(1); } - + private void stackConsume(int numItems) { for (int i = 0; i < numItems; i++) { stack.pop(); @@ -677,7 +677,7 @@ private void restoreLocals() throws Exception { endExceptionHandlers(); - + Vector<String> v = code.getActiveLocals(); loadFrame(); @@ -704,7 +704,7 @@ /** * Close all the open exception handler ranges. This should be paired * with restartExceptionHandlers to delimit internal code that - * shouldn't be handled by user handlers. This allows us to set + * shouldn't be handled by user handlers. This allows us to set * variables without the verifier thinking we might jump out of our * handling with an exception. */ @@ -864,7 +864,7 @@ "' because it is a nested function", true, node); } - + loadFrame(); code.invokestatic("org/python/core/imp", "importAll", "(" + $str + $pyFrame + ")V"); } else { @@ -939,7 +939,7 @@ public Object visitAssert(Assert node) throws Exception { setline(node); Label end_of_assert = new Label(); - + /* First do an if __debug__: */ loadFrame(); emitGetGlobal("__debug__"); @@ -961,20 +961,20 @@ if( node.getInternalMsg() != null ) { visit(node.getInternalMsg()); } else { - getNone(); + getNone(); } - + /* Push exception type onto stack(Py.AssertionError) */ code.getstatic("org/python/core/Py", "AssertionError", "Lorg/python/core/PyObject;"); - + code.swap(); // The type is the first argument, but the message could be a yield - + code.invokestatic("org/python/core/Py", "makeException", "(" + $pyObj + $pyObj + ")" + $pyExc); - + /* Raise assertion error. Only executes this logic if assertion failed */ code.athrow(); - + /* And finally set the label for the end of it all */ code.label(end_of_assert); @@ -1185,7 +1185,7 @@ code.athrow(); } - + @Override public Object visitTryFinally(TryFinally node) throws Exception { @@ -1257,14 +1257,14 @@ handler.finalBody(this); } } - + private void reenterProtectedBody(ExceptionHandler handler) throws Exception { // restart exception coverage Label restart = new Label(); code.label(restart); handler.exceptionStarts.addElement(restart); } - + /** * Inline the finally handling code for levels down to the levelth parent * (0 means all). This takes care to avoid having more nested finallys @@ -1284,7 +1284,7 @@ exceptionHandlers.push(handler); } } - + @Override public Object visitTryExcept(TryExcept node) throws Exception { Label start = new Label(); @@ -1356,10 +1356,10 @@ code.dup(); code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z"); switch (node.getInternalOp()) { - case Or : + case Or : code.ifne(end); break; - case And : + case And : code.ifeq(end); break; } @@ -1457,7 +1457,7 @@ code.invokevirtual("org/python/core/PyObject", name, "(" + $pyObj + ")" + $pyObj); return null; } - + @Override public Object visitUnaryOp(UnaryOp node) throws Exception { visit(node.getInternalOperand()); @@ -1513,10 +1513,7 @@ return null; } - - public static int makeStrings(Code c, Collection<String> names) - throws IOException - { + public static int makeStrings(Code c, Collection<String> names) { if (names != null) { c.iconst(names.size()); } else { @@ -1537,7 +1534,7 @@ } return strings; } - + public Object invokeNoKeywords(Attribute node, java.util.List<expr> values) throws Exception { @@ -1623,14 +1620,14 @@ else visit(node.getInternalKwargs()); stackProduce(); - + code.aload(argArray); code.aload(strArray); code.freeLocal(argArray); code.freeLocal(strArray); code.dup2_x2(); code.pop2(); - + stackConsume(3); // target + starargs + kwargs code.invokevirtual("org/python/core/PyObject", "_callextra", "(" + $pyObjArr + $strArr + $pyObj + $pyObj + ")" + $pyObj); @@ -1859,7 +1856,7 @@ "augmented assign to tuple not possible", node); */ if (node.getInternalCtx() == expr_contextType.Store) return seqSet(node.getInternalElts()); if (node.getInternalCtx() == expr_contextType.Del) return seqDel(node.getInternalElts()); - + int content = makeArray(node.getInternalElts()); code.new_("org/python/core/PyTuple"); @@ -1875,7 +1872,7 @@ public Object visitList(List node) throws Exception { if (node.getInternalCtx() == expr_contextType.Store) return seqSet(node.getInternalElts()); if (node.getInternalCtx() == expr_contextType.Del) return seqDel(node.getInternalElts()); - + int content = makeArray(node.getInternalElts()); code.new_("org/python/core/PyList"); @@ -1905,7 +1902,7 @@ java.util.List<expr> args = new ArrayList<expr>(); args.add(node.getInternalElt()); - stmt n = new Expr(node, new Call(node, new Name(node, tmp_append, expr_contextType.Load), + stmt n = new Expr(node, new Call(node, new Name(node, tmp_append, expr_contextType.Load), args, new ArrayList<keyword>(), null, null)); @@ -1936,7 +1933,7 @@ elts.add(node.getInternalValues().get(i)); } int content = makeArray(elts); - + code.new_("org/python/core/PyDictionary"); code.dup(); code.aload(content); @@ -1968,14 +1965,14 @@ int defaultsArray = makeArray(scope.ac.getDefaults()); code.new_("org/python/core/PyFunction"); - + code.dup(); code.aload(defaultsArray); code.freeLocal(defaultsArray); loadFrame(); code.getfield("org/python/core/PyFrame", "f_globals", $pyObj); - + code.swap(); scope.setup_closure(); @@ -2005,15 +2002,15 @@ if (node.getInternalStep() == null) getNone(); else visit(node.getInternalStep()); int step = storeTop(); stackConsume(2); - + code.new_("org/python/core/PySlice"); code.dup(); code.dup2_x2(); code.pop2(); - + code.aload(step); code.freeLocal(step); - + code.invokespecial("org/python/core/PySlice", "<init>", "(" + $pyObj + $pyObj + $pyObj + ")V"); return null; } @@ -2027,7 +2024,7 @@ //Get class name String name = getName(node.getInternalName()); code.ldc(name); - + code.aload(baseArray); ScopeInfo scope = module.getScopeInfo(node); @@ -2047,7 +2044,7 @@ } else { code.invokestatic("org/python/core/Py", "makeClass", "(" + $str + $pyObjArr + $pyCode + $pyObj + $pyObjArr + ")" + $pyObj); } - + applyDecorators(node.getInternalDecorator_list()); //Assign this new class to the given name @@ -2102,7 +2099,7 @@ expr_contextType ctx = node.getInternalCtx(); if (ctx == expr_contextType.AugStore) { ctx = augmode; - } + } switch (ctx) { case Load: @@ -2291,8 +2288,8 @@ // wrap the manager with the ContextGuard (or get it directly if it supports the ContextManager interface) code.invokestatic(Type.getType(ContextGuard.class).getInternalName(), contextGuard_getManager.getName(), contextGuard_getManager.getDescriptor()); code.dup(); - + final int mgr_tmp = code.getLocal(Type.getType(ContextManager.class).getInternalName()); code.astore(mgr_tmp); @@ -2336,7 +2333,7 @@ set(node.getInternalOptional_vars(), value_tmp); } code.freeLocal(value_tmp); - + // BLOCK + FINALLY if non-local-goto Object blockResult = suite(node.getInternalBody()); normalExit.bodyDone = true; @@ -2380,7 +2377,7 @@ handler.addExceptionHandlers(label_catch); return null; } - + @Override protected Object unhandled_node(PythonTree node) throws Exception { throw new Exception("Unhandled node " + node); @@ -2390,7 +2387,7 @@ * Data about a given exception range whether a try:finally: or a * try:except:. The finally needs to inline the finally block for * each exit of the try: section, so we carry around that data for it. - * + * * Both of these need to stop exception coverage of an area that is either * the inlined fin ally of a parent try:finally: or the reentry block after * a yield. Thus we keep around a set of exception ranges that the Modified: branches/customizable-proxymaker/src/org/python/util/jython.java =================================================================== --- branches/customizable-proxymaker/src/org/python/util/jython.java 2009-08-22 10:50:40 UTC (rev 6705) +++ branches/customizable-proxymaker/src/org/python/util/jython.java 2009-08-22 20:23:25 UTC (rev 6706) @@ -71,16 +71,17 @@ public static boolean shouldRestart; /** - * Runs a JAR file, by executing the code found in the file __run__.py, - * which should be in the root of the JAR archive. - * - * Note that the __name__ is set to the base name of the JAR file and not - * to "__main__" (for historic reasons). - * - * This method do NOT handle exceptions. the caller SHOULD handle any - * (Py)Exceptions thrown by the code. - * - * @param filename The path to the filename to run. + * Runs a JAR file, by executing the code found in the file __run__.py, which should be in the + * root of the JAR archive. + * + * Note that the __name__ is set to the base name of the JAR file and not to "__main__" (for + * historical reasons). + * + * This method does NOT catch exceptions. The caller SHOULD handle any (Py)Exceptions thrown by + * the code. + * + * @param filename + * The path to the filename to run. */ public static void runJar(String filename) { // TBD: this is kind of gross because a local called `zipfile' just magically @@ -217,7 +218,7 @@ runJar(opts.filename); } catch (Throwable t) { Py.printException(t); - System.exit(-1); + System.exit(-1); } } else if (opts.filename.equals("-")) { try { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-22 10:50:49
|
Revision: 6705 http://jython.svn.sourceforge.net/jython/?rev=6705&view=rev Author: wmeissner Date: 2009-08-22 10:50:40 +0000 (Sat, 22 Aug 2009) Log Message: ----------- First cut of minimal ctypes subset implemented via jffi Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/build.xml branches/ctypes-jffi/src/org/python/modules/Setup.java Added Paths: ----------- branches/ctypes-jffi/Lib/ctypes/ branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/extlibs/jffi-Darwin.jar branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar branches/ctypes-jffi/extlibs/jffi.jar branches/ctypes-jffi/src/org/python/modules/jffi/ branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/DirectMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/Function.java branches/ctypes-jffi/src/org/python/modules/jffi/HeapMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/Invoker.java branches/ctypes-jffi/src/org/python/modules/jffi/Memory.java branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/NativeMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/NativeType.java branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/Type.java branches/ctypes-jffi/src/org/python/modules/jffi/Util.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-08-22 07:59:45 UTC (rev 6704) +++ branches/ctypes-jffi/CoreExposed.includes 2009-08-22 10:50:40 UTC (rev 6705) @@ -52,6 +52,13 @@ org/python/modules/_csv/PyWriter.class org/python/modules/_functools/PyPartial.class org/python/modules/_hashlib$Hash.class +org/python/modules/jffi/DynamicLibrary.class +org/python/modules/jffi/DynamicLibrary$Symbol.class +org/python/modules/jffi/Function.class +org/python/modules/jffi/Pointer.class +org/python/modules/jffi/ScalarCData.class +org/python/modules/jffi/Type.class +org/python/modules/jffi/Type$Array.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class org/python/modules/_weakref/CallableProxyType.class Added: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py (rev 0) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,158 @@ +import jffi + +class _CTypeMetaClass(type): + + def __new__(cls, name, bases, dict): + return type.__new__(cls, name, bases, dict) + + def __mul__(self, len): + return _ArrayType(jffi.Type.Array(self._jffi_type, len)) + +class _ScalarCData(jffi.ScalarCData): + __metaclass__ = _CTypeMetaClass + + def size(self): + return self._jffi_type.size + + size = classmethod(size) + +class _ArrayType(object): + def __init__(self, jffi_type): + self._jffi_type = jffi_type + + def __call__(self, *args): + raise NotImplementedError("instantiating arrays is not implemented yet") + + def __len__(self): + return self._jffi_type.length + +def sizeof(type): + return type._jffi_type.size + +def alignment(type): + return type._jffi_type.alignment + +class c_byte(_ScalarCData): + _jffi_type = jffi.Type.BYTE + +class c_ubyte(_ScalarCData): + _jffi_type = jffi.Type.UBYTE + +class c_short(_ScalarCData): + _jffi_type = jffi.Type.SHORT + +class c_ushort(_ScalarCData): + _jffi_type = jffi.Type.USHORT + +class c_int(_ScalarCData): + _jffi_type = jffi.Type.INT + +class c_uint(_ScalarCData): + _jffi_type = jffi.Type.UINT + +class c_longlong(_ScalarCData): + _jffi_type = jffi.Type.LONGLONG + +class c_ulonglong(_ScalarCData): + _jffi_type = jffi.Type.ULONGLONG + +class c_long(_ScalarCData): + _jffi_type = jffi.Type.LONG + +class c_ulong(_ScalarCData): + _jffi_type = jffi.Type.ULONG + +class c_float(_ScalarCData): + _jffi_type = jffi.Type.FLOAT + +class c_double(_ScalarCData): + _jffi_type = jffi.Type.DOUBLE + +c_int8 = c_byte +c_uint8 = c_ubyte +c_int16 = c_short +c_uint16 = c_ushort +c_int32 = c_int +c_uint32 = c_uint +c_int64 = c_longlong +c_uint64 = c_ulonglong + +c_size_t = c_ulong +c_ssize_t = c_long + +class c_char_p(_ScalarCData): + _jffi_type = jffi.Type.STRING + +class c_void_p(_ScalarCData): + _jffi_type = jffi.Type.POINTER + +class _Function(jffi.Function): + _restype = c_int + _argtypes = None + + def set_restype(self, restype): + self._jffi_restype = restype._jffi_type + self._restype = restype + + def get_restype(self): + return self._restype + + def set_argtypes(self, argtypes): + jffi_types = [] + for t in argtypes: + jffi_types.append(t._jffi_type) + self._jffi_argtypes = jffi_types + self._argtypes = argtypes + + def get_argtypes(self): + return self._argtypes + + restype = property(get_restype, set_restype) + argtypes = property(get_argtypes, set_argtypes) + + +class CDLL: + DEFAULT_MODE = jffi.RTLD_GLOBAL | jffi.RTLD_LAZY + + def __init__(self, name, mode = DEFAULT_MODE, handle = None): + self._handle = jffi.dlopen(name, mode) + + def __getattr__(self, name): + if name.startswith('__') and name.endswith('__'): + raise AttributeError, name + func = self.__getitem__(name) + setattr(self, name, func) + return func + + def __getitem__(self, name): + return _Function(self._handle.find_symbol(name)) + +class LibraryLoader(object): + def __init__(self, dlltype): + self._dlltype = dlltype + + def __getattr__(self, name): + if name[0] == '_': + raise AttributeError(name) + dll = self._dlltype(name) + setattr(self, name, dll) + return dll + + def __getitem__(self, name): + return getattr(self, name) + + def LoadLibrary(self, name): + return self._dlltype(name) + +cdll = LibraryLoader(CDLL) + +# +#class _StructMetaClass(type): +# def __new__(cls, name, bases, dict): +# for attr in dict: +# if attr == '_fields_': +# print "%s has attr %s" % (name, attr) +# return type.__new__(cls, name, bases, dict) +# +#class Structure: +# __metaclass__ = _StructMetaClass Modified: branches/ctypes-jffi/build.xml =================================================================== --- branches/ctypes-jffi/build.xml 2009-08-22 07:59:45 UTC (rev 6704) +++ branches/ctypes-jffi/build.xml 2009-08-22 10:50:40 UTC (rev 6705) @@ -192,6 +192,9 @@ <pathelement path="${extlibs.dir}/constantine-0.4.jar" /> <pathelement path="${extlibs.dir}/jna.jar"/> <pathelement path="${extlibs.dir}/jna-posix.jar"/> + <pathelement path="${extlibs.dir}/jffi.jar"/> + <pathelement path="${extlibs.dir}/jffi-i386-SunOS.jar"/> + <pathelement path="${extlibs.dir}/jffi-x86_64-SunOS.jar"/> </path> <available property="informix.present" classname="com.informix.jdbc.IfxDriver" classpath="${informix.jar}" /> @@ -570,6 +573,9 @@ <zipfileset src="extlibs/asm-util-3.1.jar"/> <rule pattern="org.objectweb.asm.**" result="org.python.objectweb.asm.@1"/> <zipfileset src="extlibs/jna.jar"/> + <zipfileset src="extlibs/jffi.jar"/> + <zipfileset src="extlibs/jffi-i386-SunOS.jar"/> + <zipfileset src="extlibs/jffi-x86_64-SunOS.jar"/> <zipfileset src="extlibs/jna-posix.jar"/> <!-- <rule pattern="com.sun.jna.**" result="org.python.jna.@1"/> --> <rule pattern="org.jruby.ext.posix.**" result="org.python.posix.@1"/> Added: branches/ctypes-jffi/extlibs/jffi-Darwin.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi-Darwin.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: branches/ctypes-jffi/extlibs/jffi.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: branches/ctypes-jffi/src/org/python/modules/Setup.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/Setup.java 2009-08-22 07:59:45 UTC (rev 6704) +++ branches/ctypes-jffi/src/org/python/modules/Setup.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -56,6 +56,7 @@ "_systemrestart", "_ast:org.python.antlr.ast.AstModule", "_marshal", - "_threading:org.python.modules._threading._threading" + "_threading:org.python.modules._threading._threading", + "jffi:org.python.modules.jffi.jffi" }; } Added: branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,224 @@ + +package org.python.modules.jffi; + +import com.kenai.jffi.Platform; + +class BoundedNativeMemory implements Memory, DirectMemory { + protected static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance(); + protected static final int LONG_SIZE = Platform.getPlatform().longSize(); + protected static final int ADDRESS_SIZE = Platform.getPlatform().addressSize(); + + final long address; + final long size; + final BoundedNativeMemory parent; // keep a reference to avoid the memory being freed + + BoundedNativeMemory(long address, int size) { + this.address = address; + this.size = size; + this.parent = null; + } + + private BoundedNativeMemory(BoundedNativeMemory parent, long offset) { + this.address = parent.address + offset; + this.size = parent.size - offset; + this.parent = parent; + } + + private final void checkBounds(long off, long len) { + Util.checkBounds(size, off, len); + } + + public final long getAddress() { + return address; + } + + public BoundedNativeMemory slice(long offset) { + checkBounds(offset, 1); + return offset == 0 ? this :new BoundedNativeMemory(this, offset); + } + @Override + public final boolean equals(Object obj) { + return (obj instanceof DirectMemory) && ((DirectMemory) obj).getAddress() == address; + } + + @Override + public final int hashCode() { + int hash = 5; + hash = 53 * hash + (int) (this.address ^ (this.address >>> 32)); + return hash; + } + + public final boolean isNull() { + return address == 0; + } + + public final boolean isDirect() { + return true; + } + + public final byte getByte(long offset) { + checkBounds(offset, 1); + return IO.getByte(address + offset); + } + + public final short getShort(long offset) { + checkBounds(offset, 2); + return IO.getShort(address + offset); + } + + public final int getInt(long offset) { + checkBounds(offset, 4); + return IO.getInt(address + offset); + } + + public final long getLong(long offset) { + checkBounds(offset, 8); + return IO.getLong(address + offset); + } + + public final long getNativeLong(long offset) { + return LONG_SIZE == 32 ? getInt(offset) : getLong(offset); + } + + public final float getFloat(long offset) { + checkBounds(offset, 4); + return IO.getFloat(address + offset); + } + + public final double getDouble(long offset) { + checkBounds(offset, 8); + return IO.getDouble(address + offset); + } + + public final long getAddress(long offset) { + checkBounds(offset, ADDRESS_SIZE >> 3); + return IO.getAddress(address + offset); + } + + public final DirectMemory getMemory(long offset) { + checkBounds(offset, ADDRESS_SIZE >> 3); + final long ptr = IO.getAddress(address + offset); + return ptr != 0 ? new NativeMemory(ptr) : null; + } + + public final void putByte(long offset, byte value) { + checkBounds(offset, 1); + IO.putByte(address + offset, value); + } + + public final void putShort(long offset, short value) { + checkBounds(offset, 2); + IO.putShort(address + offset, value); + } + + public final void putInt(long offset, int value) { + checkBounds(offset, 4); + IO.putInt(address + offset, value); + } + + public final void putLong(long offset, long value) { + checkBounds(offset, 8); + IO.putLong(address + offset, value); + } + + public final void putNativeLong(long offset, long value) { + if (LONG_SIZE == 32) { + putInt(offset, (int) value); + } else { + putLong(offset, value); + } + } + public final void putAddress(long offset, long value) { + checkBounds(offset, ADDRESS_SIZE >> 3); + IO.putAddress(address + offset, value); + } + public final void putFloat(long offset, float value) { + checkBounds(offset, 4); + IO.putFloat(address + offset, value); + } + + public final void putDouble(long offset, double value) { + checkBounds(offset, 8); + IO.putDouble(address + offset, value); + } + + public final void putAddress(long offset, Memory value) { + checkBounds(offset, ADDRESS_SIZE >> 3); + IO.putAddress(address + offset, ((DirectMemory) value).getAddress()); + } + + public final void get(long offset, byte[] dst, int off, int len) { + checkBounds(offset, len); + IO.getByteArray(address + offset, dst, off, len); + } + + public final void put(long offset, byte[] src, int off, int len) { + checkBounds(offset, len); + IO.putByteArray(address + offset, src, off, len); + } + + public final void get(long offset, short[] dst, int off, int len) { + checkBounds(offset, len << 1); + IO.getShortArray(address + offset, dst, off, len); + } + + public final void put(long offset, short[] src, int off, int len) { + checkBounds(offset, len << 1); + IO.putShortArray(address + offset, src, off, len); + } + + public final void get(long offset, int[] dst, int off, int len) { + checkBounds(offset, len << 2); + IO.getIntArray(address + offset, dst, off, len); + } + + public final void put(long offset, int[] src, int off, int len) { + checkBounds(offset, len << 2); + IO.putIntArray(address + offset, src, off, len); + } + + public final void get(long offset, long[] dst, int off, int len) { + checkBounds(offset, len << 3); + IO.getLongArray(address + offset, dst, off, len); + } + + public final void put(long offset, long[] src, int off, int len) { + checkBounds(offset, len << 3); + IO.putLongArray(address + offset, src, off, len); + } + + public final void get(long offset, float[] dst, int off, int len) { + checkBounds(offset, len << 2); + IO.getFloatArray(address + offset, dst, off, len); + } + + public final void put(long offset, float[] src, int off, int len) { + checkBounds(offset, len << 2); + IO.putFloatArray(address + offset, src, off, len); + } + + public final void get(long offset, double[] dst, int off, int len) { + checkBounds(offset, len << 3); + IO.getDoubleArray(address + offset, dst, off, len); + } + + public final void put(long offset, double[] src, int off, int len) { + checkBounds(offset, len << 3); + IO.putDoubleArray(address + offset, src, off, len); + } + + public final int indexOf(long offset, byte value) { + return value == 0 + ? (int) IO.getStringLength(address + offset) + : (int) IO.indexOf(address + offset, value); + } + + public final int indexOf(long offset, byte value, int maxlen) { + return (int) IO.indexOf(address, value, maxlen); + } + + public final void setMemory(long offset, long size, byte value) { + checkBounds(offset, size); + IO.setMemory(address + offset, size, value); + } +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,433 @@ +package org.python.modules.jffi; + +import com.kenai.jffi.ArrayFlags; +import com.kenai.jffi.Function; +import com.kenai.jffi.HeapInvocationBuffer; +import com.kenai.jffi.Platform; +import org.python.core.Py; +import org.python.core.PyNone; +import org.python.core.PyObject; + +class DefaultInvokerFactory { + private static final class SingletonHolder { + public static final DefaultInvokerFactory INSTANCE = new DefaultInvokerFactory(); + } + + public static final DefaultInvokerFactory getFactory() { + return SingletonHolder.INSTANCE; + } + + private DefaultInvokerFactory() {} + + final Invoker createInvoker(com.kenai.jffi.Function function, Type[] parameterTypes, Type returnType) { + ParameterMarshaller[] marshallers = new ParameterMarshaller[parameterTypes.length]; + + for (int i = 0; i < marshallers.length; ++i) { + marshallers[i] = getMarshaller(parameterTypes[i]); + } + + + if (returnType instanceof Type.Builtin) { + switch (returnType.getNativeType()) { + case VOID: + return new VoidInvoker(function, marshallers); + + case BYTE: + return new Signed8Invoker(function, marshallers); + + case UBYTE: + return new Unsigned8Invoker(function, marshallers); + + case SHORT: + return new Signed16Invoker(function, marshallers); + + case USHORT: + return new Unsigned16Invoker(function, marshallers); + + case INT: + return new Signed32Invoker(function, marshallers); + + case UINT: + return new Unsigned32Invoker(function, marshallers); + + case LONGLONG: + return new Signed64Invoker(function, marshallers); + + case ULONGLONG: + return new Unsigned64Invoker(function, marshallers); + + case LONG: + return Platform.getPlatform().longSize() == 32 + ? new Signed32Invoker(function, marshallers) + : new Signed64Invoker(function, marshallers); + + case ULONG: + return Platform.getPlatform().longSize() == 32 + ? new Unsigned32Invoker(function, marshallers) + : new Unsigned64Invoker(function, marshallers); + case FLOAT: + return new FloatInvoker(function, marshallers); + + case DOUBLE: + return new DoubleInvoker(function, marshallers); + + case POINTER: + return new PointerInvoker(function, marshallers); + + default: + break; + } + } + throw Py.RuntimeError("Unsupported return type: " + returnType); + + } + + private static final ParameterMarshaller getMarshaller(NativeType type) { + switch (type) { + + case BYTE: + return Signed8Marshaller.INSTANCE; + case UBYTE: + return Unsigned8Marshaller.INSTANCE; + + case SHORT: + return Signed16Marshaller.INSTANCE; + case USHORT: + return Unsigned16Marshaller.INSTANCE; + + case INT: + return Signed32Marshaller.INSTANCE; + case UINT: + return Unsigned32Marshaller.INSTANCE; + + case LONGLONG: + return Signed64Marshaller.INSTANCE; + case ULONGLONG: + return Unsigned64Marshaller.INSTANCE; + + case LONG: + return Platform.getPlatform().longSize() == 32 + ? Signed32Marshaller.INSTANCE : Signed64Marshaller.INSTANCE; + case ULONG: + return Platform.getPlatform().longSize() == 32 + ? Unsigned32Marshaller.INSTANCE : Unsigned64Marshaller.INSTANCE; + + case FLOAT: + return FloatMarshaller.INSTANCE; + + case DOUBLE: + return DoubleMarshaller.INSTANCE; + + case POINTER: + return PointerMarshaller.INSTANCE; + + case STRING: + return StringMarshaller.INSTANCE; + default: + throw Py.RuntimeError("Unsupported parameter type: " + type); + } + } + + private static final ParameterMarshaller getMarshaller(Type type) { + if (type instanceof Type.Builtin) { + return getMarshaller(type.getNativeType()); + } else { + throw Py.RuntimeError("Unsupported parameter type: " + type); + } + } + + private static interface ParameterMarshaller { + void marshal(HeapInvocationBuffer buffer, PyObject arg); + } + + private static abstract class BaseInvoker implements Invoker { + final Function jffiFunction; + final com.kenai.jffi.Invoker jffiInvoker = com.kenai.jffi.Invoker.getInstance(); + final ParameterMarshaller[] marshallers; + final int arity; + + public BaseInvoker(Function function, ParameterMarshaller[] marshallers) { + this.jffiFunction= function; + this.marshallers = marshallers; + this.arity = marshallers.length; + } + + final HeapInvocationBuffer convertArguments(PyObject[] args) { + checkArity(args); + HeapInvocationBuffer buffer = new HeapInvocationBuffer(jffiFunction); + + for (int i = 0; i < marshallers.length; ++i) { + marshallers[i].marshal(buffer, args[i]); + } + + return buffer; + } + + public final PyObject invoke() { + return invoke(new PyObject[0]); + } + + public final PyObject invoke(PyObject arg0) { + return invoke(new PyObject[] { arg0 }); + } + + public final PyObject invoke(PyObject arg0, PyObject arg1) { + return invoke(new PyObject[] { arg0, arg1 }); + } + + public final PyObject invoke(PyObject arg0, PyObject arg1, PyObject arg2) { + return invoke(new PyObject[] { arg0, arg1, arg2 }); + } + + final void checkArity(PyObject[] args) { + checkArity(args.length); + } + + final void checkArity(int got) { + if (got != arity) { + throw Py.TypeError(String.format("expected %d args; got %d", arity, got)); + } + } + } + + private static final class VoidInvoker extends BaseInvoker { + + public VoidInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + jffiInvoker.invokeInt(jffiFunction, convertArguments(args)); + + return Py.None; + } + + } + private static final class Signed8Invoker extends BaseInvoker { + + public Signed8Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned8(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned8Invoker extends BaseInvoker { + + public Unsigned8Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned8(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Signed16Invoker extends BaseInvoker { + + public Signed16Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned16(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned16Invoker extends BaseInvoker { + + public Unsigned16Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned16(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Signed32Invoker extends BaseInvoker { + + public Signed32Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned32(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned32Invoker extends BaseInvoker { + + public Unsigned32Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned32(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Signed64Invoker extends BaseInvoker { + + public Signed64Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned64(jffiInvoker.invokeLong(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned64Invoker extends BaseInvoker { + + public Unsigned64Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned64(jffiInvoker.invokeLong(jffiFunction, convertArguments(args))); + } + } + + private static final class FloatInvoker extends BaseInvoker { + + public FloatInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Py.newFloat(jffiInvoker.invokeFloat(jffiFunction, convertArguments(args))); + } + } + + private static final class DoubleInvoker extends BaseInvoker { + + public DoubleInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Py.newFloat(jffiInvoker.invokeDouble(jffiFunction, convertArguments(args))); + } + } + + private static final class PointerInvoker extends BaseInvoker { + + public PointerInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Py.newLong(jffiInvoker.invokeAddress(jffiFunction, convertArguments(args))); + } + } + + /*------------------------------------------------------------------------*/ + static abstract class BaseMarshaller implements ParameterMarshaller { + } + + private static class Signed8Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed8Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putByte(Util.int8Value(arg)); + } + } + + private static class Unsigned8Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned8Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putByte((byte) Util.uint8Value(arg)); + } + } + + private static class Signed16Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed16Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putShort(Util.int16Value(arg)); + } + } + + private static class Unsigned16Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned16Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putShort((short) Util.uint16Value(arg)); + } + } + + private static class Signed32Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed32Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putInt(Util.int32Value(arg)); + } + } + + private static class Unsigned32Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned32Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putInt((int) Util.int32Value(arg)); + } + } + + private static class Signed64Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed64Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putLong(Util.int64Value(arg)); + } + } + + private static class Unsigned64Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned64Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putLong(Util.uint64Value(arg)); + } + } + + private static class FloatMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new FloatMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putFloat((float) arg.asDouble()); + } + } + + private static class DoubleMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new DoubleMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putDouble(arg.asDouble()); + } + } + + private static class StringMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new StringMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { + if (parameter instanceof PyNone) { + buffer.putAddress(0); + } else { + byte[] bytes = parameter.toString().getBytes(); + buffer.putArray(bytes, 0, bytes.length, + ArrayFlags.IN | ArrayFlags.NULTERMINATE); + } + } + } + + private static class PointerMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new PointerMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { + throw Py.NotImplementedError("POINTER parameters not implemented"); + } + } + +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/DirectMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DirectMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DirectMemory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,6 @@ + +package org.python.modules.jffi; + +public interface DirectMemory extends Memory { + long getAddress(); +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,86 @@ + +package org.python.modules.jffi; + +import com.kenai.jffi.Library; +import org.python.core.ClassDictInit; +import org.python.core.Py; +import org.python.core.PyObject; +import org.python.core.PyType; +import org.python.expose.ExposeAsSuperclass; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.DynamicLibrary", base = PyObject.class) +public class DynamicLibrary extends PyObject { + + public static final PyType TYPE = PyType.fromClass(DynamicLibrary.class); + + @ExposedGet + public final String name; + private final com.kenai.jffi.Library lib; + + DynamicLibrary(String libname, int mode) { + this.name = libname; + lib = Library.getCachedInstance(libname, mode); + + if (lib == null) { + throw Py.RuntimeError("Could not open " + + libname != null ? libname : "[current process]" + + " " + Library.getLastError()); + } + } + + private long findSymbol(PyObject name) { + long address = lib.getSymbolAddress(name.asString()); + if (address == 0) { + throw Py.NameError("Could not locate symbol '" + name.asString() + "' in " + this.name); + } + + return address; + } + + @ExposedMethod + public final PyObject find_symbol(PyObject name) { + long address = findSymbol(name); + return new Symbol(this, name.asString(), address, new NativeMemory(address)); + } + + @ExposedMethod + public final PyObject find_function(PyObject name) { + return new TextSymbol(this, name.asString(), findSymbol(name)); + } + + @ExposedMethod + public final PyObject find_variable(PyObject name) { + return new DataSymbol(this, name.asString(), findSymbol(name)); + } + + @ExposedType(name = "jffi.DynamicLibrary.Symbol", base = Pointer.class) + public static class Symbol extends Pointer { + public static final PyType TYPE = PyType.fromClass(Symbol.class); + + final DynamicLibrary library; + + @ExposedGet + public final String name; + + public Symbol(DynamicLibrary library, String name, long address, DirectMemory memory) { + super(address, memory); + this.library = library; + this.name = name; + } + } + + public static class TextSymbol extends Symbol implements ExposeAsSuperclass { + public TextSymbol(DynamicLibrary lib, String name, long address) { + super(lib, name, address, new NativeMemory(address)); + } + } + + public static class DataSymbol extends Symbol implements ExposeAsSuperclass { + public DataSymbol(DynamicLibrary lib, String name, long address) { + super(lib, name, address, new NativeMemory(address)); + } + } +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,647 @@ + +package org.python.modules.jffi; + +import com.kenai.jffi.Function; +import com.kenai.jffi.Platform; +import org.python.core.Py; +import org.python.core.PyObject; + + +/** + * A factory which generates {@link Invoker} instances that are optimized for + * 32 bit integer and float parameters / result types with 3 or less parameters. + * + * Technical background: Instead of trying to cram all calls down a generic call + * path, then figuring out how to convert the parameters in the native code on + * each call, jffi supplies arity and type specific call paths that can be + * optimized ahead of time by the native code. + * + * The downside of this approach is more java code to wire up the functions and + * call them using the arity+type specific paths, but in the case of int and float + * parameters, it can result in more than a 100% speed boost over the generic path. + */ +public class FastIntInvokerFactory { + private static final class SingletonHolder { + private static final FastIntInvokerFactory INSTANCE = new FastIntInvokerFactory(); + } + + private FastIntInvokerFactory() {} + + public static final FastIntInvokerFactory getFactory() { + return SingletonHolder.INSTANCE; + } + + /** + * Interface used to convert from a python object to a native integer + */ + private static interface IntParameterConverter { + int intValue(PyObject value); + } + + /** + * Interface used to convert from a native integer to a python object + */ + private static interface IntResultConverter { + PyObject pyValue(int value); + } + + /** + * Tests if a combination of result and parameter types can be called using + * an {@link Invoker} created by this factory. + * + * @param returnType The return type of the native function. + * @param parameterTypes The parameter types of the native function. + * @return <tt>true</tt> if the method can be handled as a fast int method. + */ + final boolean isFastIntMethod(Type returnType, Type[] parameterTypes) { + for (int i = 0; i < parameterTypes.length; ++i) { + if (!isFastIntParam(parameterTypes[i])) { + return false; + } + } + return parameterTypes.length <= 3 && isFastIntResult(returnType); + } + + /** + * Tests if the type can be returned as an integer result. + * + * @param type The result type. + * @return <tt>true</tt> if <tt>type</tt> can be returned as an integer. + */ + final boolean isFastIntResult(Type type) { + if (type instanceof Type.Builtin) { + switch (type.getNativeType()) { + case VOID: + case BYTE: + case UBYTE: + case SHORT: + case USHORT: + case INT: + case UINT: + return true; + + case LONG: + case ULONG: + return Platform.getPlatform().longSize() == 32; + + case FLOAT: + return Platform.getPlatform().getCPU() == Platform.CPU.I386 + || Platform.getPlatform().getCPU() == Platform.CPU.X86_64; + } + } + return false; + } + + + /** + * Tests if the type can be passed as an integer parameter. + * + * @param type The parameter type. + * @return <tt>true</tt> if <tt>type</tt> can be passed as an integer. + */ + final boolean isFastIntParam(Type paramType) { + if (paramType instanceof Type.Builtin) { + switch (paramType.getNativeType()) { + case BYTE: + case UBYTE: + case SHORT: + case USHORT: + case INT: + case UINT: + return true; + + case LONG: + case ULONG: + return Platform.getPlatform().longSize() == 32; + + case FLOAT: + return Platform.getPlatform().getCPU() == Platform.CPU.I386 + || Platform.getPlatform().getCPU() == Platform.CPU.X86_64; + } + } + return false; + } + + + /** + * Creates a new <tt>Invoker</tt> instance for the given function, with the + * given parameter types and return type. + * + * @param function The JFFI function to wrap + * @param parameterTypes The parameter types the function will be called with + * @param returnType The result type the function will return + * @return A new {@link Invoker} instance. + */ + final Invoker createInvoker(Function function, Type[] parameterTypes, Type returnType) { + IntParameterConverter[] parameterConverters = new IntParameterConverter[parameterTypes.length]; + + for (int i = 0; i < parameterConverters.length; ++i) { + parameterConverters[i] = getIntParameterConverter(parameterTypes[i]); + } + if (returnType.nativeType == NativeType.FLOAT) { + switch (parameterTypes.length) { + case 0: + return new FastFloatInvokerZero(function, null, parameterConverters); + case 1: + return new FastFloatInvokerOne(function, null, parameterConverters); + case 2: + return new FastFloatInvokerTwo(function, null, parameterConverters); + case 3: + return new FastFloatInvokerThree(function, null, parameterConverters); + } + } else { + IntResultConverter resultConverter = getIntResultConverter(returnType); + switch (parameterTypes.length) { + case 0: + return new FastIntInvokerZero(function, resultConverter, parameterConverters); + case 1: + return new FastIntInvokerOne(function, resultConverter, parameterConverters); + case 2: + return new FastIntInvokerTwo(function, resultConverter, parameterConverters); + case 3: + return new FastIntInvokerThree(function, resultConverter, parameterConverters); + } + } + throw Py.RuntimeError("Fast Integer invoker does not support functions with arity=" + parameterTypes.length); + } + + /** + * Gets a python object to integer parameter converter. + * + * @param type The python C type + * @return An <tt>IntParameterConverter</tt> instance. + */ + final IntParameterConverter getIntParameterConverter(Type type) { + if (type instanceof Type.Builtin) { + return getIntParameterConverter(type.getNativeType()); + } + throw Py.TypeError("cannot convert objects of type " + type + " to int"); + } + + + /** + * Gets a python object to integer parameter converter. + * + * @param type The object type. + * @return An <tt>IntParameterConverter</tt> instance. + */ + final IntParameterConverter getIntParameterConverter(NativeType type) { + switch (type) { + case BYTE: + return Signed8ParameterConverter.INSTANCE; + + case UBYTE: + return Unsigned8ParameterConverter.INSTANCE; + + case SHORT: + return Signed16ParameterConverter.INSTANCE; + + case USHORT: + return Unsigned16ParameterConverter.INSTANCE; + + case INT: + return Signed32ParameterConverter.INSTANCE; + + case UINT: + return Unsigned32ParameterConverter.INSTANCE; + + case LONG: + if (Platform.getPlatform().longSize() == 32) { + return Signed32ParameterConverter.INSTANCE; + } + break; + + case ULONG: + if (Platform.getPlatform().longSize() == 32) { + return Unsigned32ParameterConverter.INSTANCE; + } + break; + + case FLOAT: + if (Platform.getPlatform().getCPU() == Platform.CPU.I386 + || Platform.getPlatform().getCPU() == Platform.CPU.X86_64) { + return Float32ParameterConverter.INSTANCE; + } + break; + default: + break; + } + + throw Py.TypeError("cannot convert objects of type " + type + " to int"); + } + + + /** + * Gets a int to python object result converter for the type. + * + * @param type The object type. + * @return An <tt>IntResultConverter</tt> instance. + */ + final IntResultConverter getIntResultConverter(Type type) { + return type instanceof Type.Builtin ? getIntResultConverter(type.getNativeType()) : null; + } + + + /** + * Gets a int to python object result converter for the type. + * + * @param type The object type. + * @return An <tt>IntResultConverter</tt> instance. + */ + final IntResultConverter getIntResultConverter(NativeType type) { + switch (type) { + case VOID: + return VoidResultConverter.INSTANCE; + + case BYTE: + return Signed8ResultConverter.INSTANCE; + + case UBYTE: + return Unsigned8ResultConverter.INSTANCE; + + case SHORT: + return Signed16ResultConverter.INSTANCE; + + case USHORT: + return Unsigned16ResultConverter.INSTANCE; + + case INT: + return Signed32ResultConverter.INSTANCE; + + case UINT: + return Unsigned32ResultConverter.INSTANCE; + + case LONG: + if (Platform.getPlatform().longSize() == 32) { + return Signed32ResultConverter.INSTANCE; + } + break; + + case ULONG: + if (Platform.getPlatform().longSize() == 32) { + return Unsigned32ResultConverter.INSTANCE; + } + break; + + default: + break; + } + throw new IllegalArgumentException("Cannot convert objects of type " + type + " from int"); + } + + /** + * Base class for all fast-int {@link Invoker} subclasses + */ + private static abstract class BaseFastIntInvoker implements Invoker { + final com.kenai.jffi.Invoker jffiInvoker = com.kenai.jffi.Invoker.getInstance(); + final Function function; + final IntResultConverter resultConverter; + final int arity; + final IntParameterConverter c0, c1, c2; + + BaseFastIntInvoker(Function function, IntResultConverter resultConverter, + IntParameterConverter[] parameterConverters) { + this.function = function; + this.resultConverter = resultConverter; + this.arity = parameterConverters.length; + c0 = parameterConverters.length > 0 ? parameterConverters[0] : null; + c1 = parameterConverters.length > 1 ? parameterConverters[1] : null; + c2 = parameterConverters.length > 2 ? parameterConverters[2] : null; + } + + final void checkArity(PyObject[] args) { + checkArity(args.length); + } + + final void checkArity(int got) { + if (got != arity) { + throw Py.TypeError(String.format("__call__() takes exactly %d arguments (%d given)", arity, got)); + } + } + public PyObject invoke(PyObject[] args) { + checkArity(args); + switch (arity) { + case 0: + return invoke(); + case 1: + return invoke(args[0]); + case 2: + return invoke(args[0], args[1]); + case 3: + return invoke(args[0], args[1], args[2]); + default: + throw Py.RuntimeError("invalid fast-int arity"); + } + } + + public PyObject invoke() { + checkArity(0); + return Py.None; + } + + public PyObject invoke(PyObject arg1) { + checkArity(1); + return Py.None; + } + + public PyObject invoke(PyObject arg1, PyObject arg2) { + checkArity(2); + return Py.None; + } + + public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) { + checkArity(3); + return Py.None; + } + + } + + /** + * Fast-int invoker that takes no parameters. + */ + private static final class FastIntInvokerZero extends BaseFastIntInvoker { + + public FastIntInvokerZero(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public final PyObject invoke() { + return resultConverter.pyValue(jffiInvoker.invokeVrI(function)); + } + } + + /** + * Fast-int invoker that takes a single parameter + */ + private static final class FastIntInvokerOne extends BaseFastIntInvoker { + public FastIntInvokerOne(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + + } + + @Override + public final PyObject invoke(PyObject arg0) { + return resultConverter.pyValue(jffiInvoker.invokeIrI(function, + c0.intValue(arg0))); + } + } + + + /** + * Fast-int invoker that takes two parameters + */ + private static final class FastIntInvokerTwo extends BaseFastIntInvoker { + + public FastIntInvokerTwo(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1) { + return resultConverter.pyValue(jffiInvoker.invokeIIrI(function, + c0.intValue(arg0), c1.intValue(arg1))); + } + } + + /** + * Fast-int invoker that takes three parameters + */ + private static final class FastIntInvokerThree extends BaseFastIntInvoker { + + public FastIntInvokerThree(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1, PyObject arg2) { + return resultConverter.pyValue(jffiInvoker.invokeIIIrI(function, + c0.intValue(arg0), c1.intValue(arg1), c2.intValue(arg2))); + } + } + + /** + * Fast-int invoker that takes no parameters and returns a float + */ + private static final class FastFloatInvokerZero extends BaseFastIntInvoker { + + public FastFloatInvokerZero(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public final PyObject invoke() { + return Py.newFloat(jffiInvoker.invokeVrF(function)); + } + } + + /** + * Fast-int invoker that takes one parameter and returns a float + */ + private static final class FastFloatInvokerOne extends BaseFastIntInvoker { + + public FastFloatInvokerOne(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public final PyObject invoke(PyObject arg0) { + return Py.newFloat(jffiInvoker.invokeIrF(function, + c0.intValue(arg0))); + } + } + + + /** + * Fast-int invoker that takes two parameters and returns a float + */ + private static final class FastFloatInvokerTwo extends BaseFastIntInvoker { + + public FastFloatInvokerTwo(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1) { + return Py.newFloat(jffiInvoker.invokeIIrF(function, + c0.intValue(arg0), c1.intValue(arg1))); + } + } + + /** + * Fast-int invoker that takes three parameters and returns a float + */ + private static final class FastFloatInvokerThree extends BaseFastIntInvoker { + + public FastFloatInvokerThree(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1, PyObject arg2) { + return Py.newFloat(jffiInvoker.invokeIIIrF(function, + c0.intValue(arg0), c1.intValue(arg1), c2.intValue(arg2))); + } + } + + /** + * Base class for all fast-int result converters + */ + static abstract class BaseResultConverter implements IntResultConverter { + + } + + /** + * Converts a native void result into into a python None instance + */ + static final class VoidResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new VoidResultConverter(); + public final PyObject pyValue(int value) { + return Py.None; + } + } + + /** + * Converts a native signed byte result into into a python integer instance + */ + static final class Signed8ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Signed8ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newSigned8(value); + } + } + + /** + * Converts a native unsigned byte result into into a python integer instance + */ + static final class Unsigned8ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Unsigned8ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newUnsigned8(value); + } + } + + /** + * Converts a native signed short result into into a python integer instance + */ + static final class Signed16ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Signed16ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newSigned16(value); + } + } + + /** + * Converts a native unsigned short result into into a python integer instance + */ + static final class Unsigned16ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Unsigned16ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newUnsigned16(value); + } + } + + /** + * Converts a native signed int result into into a python integer instance + */ + static final class Signed32ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Signed32ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newSigned32(value); + } + } + + /** + * Converts a native unsigned int result into into a python integer instance + */ + static final class Unsigned32ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Unsigned32ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newUnsigned32(value); + } + } + + /** + * Base class for all integer parameter converters. + */ + static abstract class BaseParameterConverter implements IntParameterConverter { + } + + /** + * Converter for python signed byte to native int + */ + static final class Signed8ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Signed8ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.int8Value(obj); + } + } + + /** + * Converter for python unsigned byte to native int + */ + static final class Unsigned8ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Unsigned8ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.uint8Value(obj); + } + } + + /** + * Converter for python signed short to native int + */ + static final class Signed16ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Signed16ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.int16Value(obj); + } + } + + /** + * Converter for python unsigned short to native int + */ + static final class Unsigned16ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Unsigned16ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.uint16Value(obj); + } + } + + /** + * Converter for python signed int to native int + */ + static final class Signed32ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Signed32ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.int32Value(obj); + } + } + + /** + * Converter for python unsigned int to native int + */ + static final class Unsigned32ParameterConverter extends BaseParameterConverter { + ... [truncated message content] |
From: <cg...@us...> - 2009-08-22 07:59:53
|
Revision: 6704 http://jython.svn.sourceforge.net/jython/?rev=6704&view=rev Author: cgroves Date: 2009-08-22 07:59:45 +0000 (Sat, 22 Aug 2009) Log Message: ----------- Cleanup Modified Paths: -------------- branches/customizable-proxymaker/src/org/python/core/ParserFacade.java branches/customizable-proxymaker/src/org/python/core/PyProxy.java branches/customizable-proxymaker/src/org/python/core/util/ByteSwapper.java Modified: branches/customizable-proxymaker/src/org/python/core/ParserFacade.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/ParserFacade.java 2009-08-22 07:53:18 UTC (rev 6703) +++ branches/customizable-proxymaker/src/org/python/core/ParserFacade.java 2009-08-22 07:59:45 UTC (rev 6704) @@ -4,14 +4,11 @@ import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringReader; -import java.io.Writer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; @@ -25,7 +22,6 @@ import org.python.antlr.BaseParser; import org.python.antlr.NoCloseReaderStream; import org.python.antlr.ParseException; -import org.python.antlr.PythonLexer; import org.python.antlr.PythonPartialLexer; import org.python.antlr.PythonPartialParser; import org.python.antlr.PythonTokenSource; @@ -173,7 +169,7 @@ close(bufReader); } } - + public static mod parse(InputStream stream, CompileMode kind, String filename, @@ -272,7 +268,7 @@ throws IOException { cflags.source_is_utf8 = true; cflags.encoding = "utf-8"; - + BufferedReader bufferedReader = new BufferedReader(reader); bufferedReader.mark(MARK_LIMIT); if (findEncoding(bufferedReader) != null) Modified: branches/customizable-proxymaker/src/org/python/core/PyProxy.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyProxy.java 2009-08-22 07:53:18 UTC (rev 6703) +++ branches/customizable-proxymaker/src/org/python/core/PyProxy.java 2009-08-22 07:59:45 UTC (rev 6704) @@ -34,7 +34,7 @@ * Associate an system state with this proxy instance. This is done during construction and * initialization of the proxy instance. */ - abstract public void _setPySystemState(PySystemState ss); + void _setPySystemState(PySystemState ss); /** * Return the associated system state. Modified: branches/customizable-proxymaker/src/org/python/core/util/ByteSwapper.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/util/ByteSwapper.java 2009-08-22 07:53:18 UTC (rev 6703) +++ branches/customizable-proxymaker/src/org/python/core/util/ByteSwapper.java 2009-08-22 07:59:45 UTC (rev 6704) @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ * </ul> * <p /> * Note this functionality is provided in the base types since 1.5. - * + * * @author Andrew Howard */ public class ByteSwapper { @@ -38,7 +38,7 @@ /** * Reverses the byte order of all elements in the supplied array, converting * between little and big endian byte order. - * + * * @param array the input array for type sensitive byte swapping. */ public static void swap(Object array) { @@ -68,7 +68,7 @@ /** * Byte order reverses an <code>Array</code> of <code>doubles</code> - * + * * @param array input array */ private static void swapDoubleArray(Object array) { @@ -99,7 +99,7 @@ /** * Byte order reverses an <code>Array</code> of <code>floats</code> - * + * * @param array input array */ private static void swapFloatArray(Object array) { @@ -125,7 +125,7 @@ /** * Byte order reverses an <code>Array</code> of <code>ints</code> - * + * * @param array input array */ private static void swapIntegerArray(Object array) { @@ -148,7 +148,7 @@ /** * Byte order reverses an <code>Array</code> of <code>longs</code> - * + * * @param array input array */ private static void swapLongArray(Object array) { @@ -176,7 +176,7 @@ /** * Byte order reverses an <code>Array</code> of <code>shorts</code> - * + * * @param array input array */ private static void swapShortArray(Object array) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-08-22 07:53:28
|
Revision: 6703 http://jython.svn.sourceforge.net/jython/?rev=6703&view=rev Author: cgroves Date: 2009-08-22 07:53:18 +0000 (Sat, 22 Aug 2009) Log Message: ----------- Split the bits of PyType used to configure and initialize runtime types into PyUserType and move the bits that do the same for @Exposed classes and java types into PyBuiltinType. PyType just keeps the implementation of type logic and the fields necessary for that. I'd been worried that PyType was going to gain sentience and eat Chicago if it got any larger. Modified Paths: -------------- branches/customizable-proxymaker/src/org/python/core/PyClass.java branches/customizable-proxymaker/src/org/python/core/PyJavaType.java branches/customizable-proxymaker/src/org/python/core/PyType.java branches/customizable-proxymaker/src/templates/type.derived Added Paths: ----------- branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java branches/customizable-proxymaker/src/org/python/core/PyUserType.java branches/customizable-proxymaker/src/org/python/core/PyUserTypeDerived.java Removed Paths: ------------- branches/customizable-proxymaker/src/org/python/core/PyTypeDerived.java Added: branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java (rev 0) +++ branches/customizable-proxymaker/src/org/python/core/PyBuiltinType.java 2009-08-22 07:53:18 UTC (rev 6703) @@ -0,0 +1,218 @@ +package org.python.core; + +import java.util.Map; +import java.util.Set; + +import org.python.expose.ExposeAsSuperclass; +import org.python.expose.ExposedType; +import org.python.expose.TypeBuilder; +import org.python.util.Generic; + + +public class PyBuiltinType extends PyType { + + /** Mapping of Java classes to their PyTypes. */ + private static Map<Class<?>, PyBuiltinType> class_to_type; + + /** Mapping of Java classes to their TypeBuilders. */ + private static Map<Class<?>, TypeBuilder> classToBuilder; + + PyBuiltinType(PyType pyType) { + super(pyType); + } + + private PyBuiltinType() { + } + + private PyBuiltinType(boolean b) { + super(b); + } + + public static synchronized PyBuiltinType fromClass(Class<?> c) { + if (c == PyBuiltinType.class) { + return fromClass(PyType.class); + } + if (class_to_type == null) { + class_to_type = Generic.map(); + addFromClass(PyType.class, null); + } + PyBuiltinType type = class_to_type.get(c); + if (type != null) { + return type; + } + // We haven't seen this class before, so it's 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<PyJavaType> needsInners = Generic.set(); + PyBuiltinType result = addFromClass(c, needsInners); + for (PyJavaType javaType : needsInners) { + Class<?> forClass = javaType.getProxyType(); + if (forClass == null) { + 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 + if (inner.getAnnotation(ExposedType.class) != null + || ExposeAsSuperclass.class.isAssignableFrom(inner)) { + Py.BOOTSTRAP_TYPES.add(inner); + } + javaType.dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner)); + } + } + } + return result; + } + + public static void addBuilder(Class<?> forClass, TypeBuilder builder) { + + if (classToBuilder == null) { + classToBuilder = Generic.map(); + } + classToBuilder.put(forClass, builder); + + if (class_to_type.containsKey(forClass)) { + if (!Py.BOOTSTRAP_TYPES.remove(forClass)) { + Py.writeWarning("init", "Bootstrapping class not in Py.BOOTSTRAP_TYPES[class=" + + forClass + "]"); + } + // The types in Py.BOOTSTRAP_TYPES are initialized before their builders are assigned, + // so do the work of addFromClass & fillFromClass after the fact + PyBuiltinType.fromClass(builder.getTypeClass()).init(builder.getTypeClass(), null); + } + } + + /** + * Called on builtin types for a particular class. Should fill in dict, name, mro, base and + * bases from the class. + */ + protected void init(Class<?> forClass, Set<PyJavaType> needsInners) { + underlying_class = forClass; + if (underlying_class == PyObject.class) { + mro = new PyType[] {this}; + } else { + Class<?> baseClass; + if (!Py.BOOTSTRAP_TYPES.contains(underlying_class)) { + baseClass = classToBuilder.get(underlying_class).getBase(); + } else { + baseClass = PyObject.class; + } + if (baseClass == Object.class) { + baseClass = underlying_class.getSuperclass(); + } + computeLinearMro(baseClass); + } + if (Py.BOOTSTRAP_TYPES.contains(underlying_class)) { + // init will be called again from addBuilder which also removes underlying_class from + // BOOTSTRAP_TYPES + return; + } + TypeBuilder builder = classToBuilder.get(underlying_class); + name = builder.getName(); + dict = builder.getDict(this); + setIsBaseType(builder.getIsBaseType()); + instantiable = dict.__finditem__("__new__") != null; + fillHasSetAndDelete(); + } + + /** + * Fills the base and bases of this type with the type of baseClass as sets its mro to this type + * followed by the mro of baseClass. + */ + protected void computeLinearMro(Class<?> baseClass) { + base = PyType.fromClass(baseClass); + mro = new PyType[base.mro.length + 1]; + System.arraycopy(base.mro, 0, mro, 1, base.mro.length); + mro[0] = this; + bases = new PyObject[] {base}; + } + + private void setIsBaseType(boolean isBaseType) { + this.isBaseType = isBaseType; + tp_flags = isBaseType ? tp_flags | Py.TPFLAGS_BASETYPE : tp_flags & ~Py.TPFLAGS_BASETYPE; + } + + private static PyBuiltinType addFromClass(Class<?> c, Set<PyJavaType> needsInners) { + if (ExposeAsSuperclass.class.isAssignableFrom(c)) { + PyBuiltinType exposedAs = fromClass(c.getSuperclass()); + class_to_type.put(c, exposedAs); + return exposedAs; + } + return createType(c, needsInners); + } + + private static TypeBuilder getBuilder(Class<?> c) { + if (classToBuilder == null) { + // PyType itself has yet to be initialized. This should be a bootstrap type, so it'll + // go through the builder process in a second + return null; + } + 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 + return null; + } + + // 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 = classToBuilder.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 static PyBuiltinType createType(Class<?> c, Set<PyJavaType> needsInners) { + PyBuiltinType newtype; + if (c == PyJavaType.class) { + return (PyBuiltinType)PyType.fromClass(Class.class); + } else if (c == PyType.class) { + newtype = new PyBuiltinType(false); + } else if (Py.BOOTSTRAP_TYPES.contains(c) || getBuilder(c) != null) { + newtype = new PyBuiltinType(); + } else { + newtype = new PyJavaType(); + } + + + // If filling in the type above filled the type under creation, use that one + PyBuiltinType type = class_to_type.get(c); + if (type != null) { + return type; + } + + class_to_type.put(c, newtype); + newtype.builtin = true; + newtype.init(c, needsInners); + return newtype; + } + + static PyType fromClassSkippingInners(Class<?> c, Set<PyJavaType> needsInners) { + PyType type = class_to_type.get(c); + if (type != null) { + return type; + } + return addFromClass(c, needsInners); + } +} Modified: branches/customizable-proxymaker/src/org/python/core/PyClass.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyClass.java 2009-08-22 07:46:25 UTC (rev 6702) +++ branches/customizable-proxymaker/src/org/python/core/PyClass.java 2009-08-22 07:53:18 UTC (rev 6703) @@ -48,8 +48,8 @@ if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { throw Py.TypeError("PyClass_New: dict must be a dictionary"); } - PyType.ensureDoc(dict); - PyType.ensureModule(dict); + PyUserType.ensureDoc(dict); + PyUserType.ensureModule(dict); if (!(bases instanceof PyTuple)) { throw Py.TypeError("PyClass_New: bases must be a tuple"); Modified: branches/customizable-proxymaker/src/org/python/core/PyJavaType.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyJavaType.java 2009-08-22 07:46:25 UTC (rev 6702) +++ branches/customizable-proxymaker/src/org/python/core/PyJavaType.java 2009-08-22 07:53:18 UTC (rev 6703) @@ -17,7 +17,7 @@ import org.python.core.util.StringUtil; import org.python.util.Generic; -public class PyJavaType extends PyType { +public class PyJavaType extends PyBuiltinType { private final static Class<?>[] OO = {PyObject.class, PyObject.class}; @@ -188,7 +188,7 @@ } else { needsInners.add(this); javaProxy = forClass; - objtype = PyType.fromClassSkippingInners(Class.class, needsInners); + objtype = PyBuiltinType.fromClassSkippingInners(Class.class, needsInners); // Wrapped Java types fill in their mro first using all of their interfaces then their // super class. List<PyObject> visibleBases = Generic.list(); @@ -205,16 +205,16 @@ // in the hierarchy, adding it here hides the forms from those interfaces. continue; } - visibleBases.add(PyType.fromClassSkippingInners(iface, needsInners)); + visibleBases.add(PyBuiltinType.fromClassSkippingInners(iface, needsInners)); } if (javaProxy == Object.class) { - base = PyType.fromClassSkippingInners(PyObject.class, needsInners); + base = PyBuiltinType.fromClassSkippingInners(PyObject.class, needsInners); } else if(baseClass == null) { - base = PyType.fromClassSkippingInners(Object.class, needsInners); + base = PyBuiltinType.fromClassSkippingInners(Object.class, needsInners); }else if (javaProxy == Class.class) { - base = PyType.fromClassSkippingInners(PyType.class, needsInners); + base = PyBuiltinType.fromClassSkippingInners(PyType.class, needsInners); } else { - base = PyType.fromClassSkippingInners(baseClass, needsInners); + base = PyBuiltinType.fromClassSkippingInners(baseClass, needsInners); } visibleBases.add(base); this.bases = visibleBases.toArray(new PyObject[visibleBases.size()]); Modified: branches/customizable-proxymaker/src/org/python/core/PyType.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyType.java 2009-08-22 07:46:25 UTC (rev 6702) +++ branches/customizable-proxymaker/src/org/python/core/PyType.java 2009-08-22 07:53:18 UTC (rev 6703) @@ -7,10 +7,8 @@ import java.lang.ref.WeakReference; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; -import org.python.expose.ExposeAsSuperclass; import org.python.expose.ExposedDelete; import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; @@ -18,7 +16,6 @@ import org.python.expose.ExposedSet; import org.python.expose.ExposedType; import org.python.expose.TypeBuilder; -import org.python.modules._weakref.WeakrefModule; import org.python.util.Generic; /** @@ -47,9 +44,6 @@ /** __mro__, the method resolution. order */ protected PyObject[] mro; - /** __flags__, the type's options. */ - 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. @@ -62,46 +56,43 @@ /** Whether new instances of this type can be instantiated */ protected boolean instantiable = true; + /** Whether this type has a __dict__. */ + protected boolean needs_userdict; + + /** __flags__, the type's options. */ + long tp_flags; + /** Whether this type has set/delete descriptors */ boolean has_set; boolean has_delete; /** Whether this type allows subclassing. */ - private boolean isBaseType = true; + boolean isBaseType = true; - /** Whether this type has a __dict__. */ - protected boolean needs_userdict; - /** Whether this type has a __weakref__ slot (however all types are weakrefable). */ - protected boolean needs_weakref; + boolean needs_weakref; /** Whether finalization is required for this type's instances (implements __del__). */ - private boolean needs_finalizer; + boolean needs_finalizer; /** The number of __slots__ defined. */ - private int numSlots; + int numSlots; private ReferenceQueue<PyType> subclasses_refq = new ReferenceQueue<PyType>(); private Set<WeakReference<PyType>> subclasses = Generic.set(); - /** Mapping of Java classes to their PyTypes. */ - private static Map<Class<?>, PyType> class_to_type; - - /** Mapping of Java classes to their TypeBuilders. */ - private static Map<Class<?>, TypeBuilder> classToBuilder; - protected PyType(PyType subtype) { super(subtype); } - private PyType() { + PyType() { } /** * Creates the PyType instance for type itself. The argument just exists to make the constructor * distinct. */ - private PyType(boolean ignored) { + PyType(boolean ignored) { super(ignored); } @@ -130,8 +121,7 @@ public static PyObject newType(PyNewWrapper new_, PyType metatype, String name, PyTuple bases, PyObject dict) { - PyObject[] tmpBases = bases.getArray(); - PyType winner = findMostDerivedMetatype(tmpBases, metatype); + PyType winner = findMostDerivedMetatype(bases, metatype); if (winner != metatype) { PyObject winner_new_ = winner.lookup("__new__"); @@ -150,281 +140,13 @@ metatype = TYPE; } - PyType type; if (new_.for_type == metatype) { - // XXX: set metatype - type = new PyType(); + return new PyUserType(TYPE, name, bases, dict); } else { - type = new PyTypeDerived(metatype); + return new PyUserTypeDerived(metatype, name, bases, dict); } - - if (dict instanceof PyStringMap) { - dict = ((PyStringMap)dict).copy(); - } else { - dict = ((PyDictionary)dict).copy(); - } - - type.name = name; - type.bases = tmpBases.length == 0 ? new PyObject[] {PyObject.TYPE} : tmpBases; - type.dict = dict; - type.tp_flags = Py.TPFLAGS_HEAPTYPE | Py.TPFLAGS_BASETYPE; - - // immediately setup the javaProxy if applicable. may modify bases - List<Class<?>> interfaces = Generic.list(); - Class<?> baseProxyClass = getJavaLayout(type.bases, interfaces); - type.setupProxy(baseProxyClass, interfaces); - - 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)); - } - - type.createAllSlots(!base.needs_userdict, !base.needs_weakref); - type.ensureAttributes(); - - for (PyObject cur : type.bases) { - if (cur instanceof PyType) - ((PyType)cur).attachSubclass(type); - } - - return type; } - /** - * Create all slots and related descriptors. - * - * @param mayAddDict whether a __dict__ descriptor is allowed on this type - * @param mayAddWeak whether a __weakref__ descriptor is allowed on this type - */ - private void createAllSlots(boolean mayAddDict, boolean mayAddWeak) { - numSlots = base.numSlots; - boolean wantDict = false; - boolean wantWeak = false; - PyObject slots = dict.__finditem__("__slots__"); - - if (slots == null) { - wantDict = mayAddDict; - wantWeak = mayAddWeak; - } else { - if (slots instanceof PyString) { - slots = new PyTuple(slots); - } - - // Check for valid slot names and create them. Handle two special cases - for (PyObject slot : slots.asIterable()) { - String slotName = confirmIdentifier(slot); - - if (slotName.equals("__dict__")) { - if (!mayAddDict || wantDict) { - throw Py.TypeError("__dict__ slot disallowed: we already got one"); - } - wantDict = true; - } else if (slotName.equals("__weakref__")) { - if (!mayAddWeak || wantWeak) { - throw Py.TypeError("__weakref__ slot disallowed: we already got one"); - } - wantWeak = true; - } else { - slotName = mangleName(name, slotName); - if (dict.__finditem__(slotName) == null) { - dict.__setitem__(slotName, new PySlot(this, slotName, numSlots++)); - } - } - } - - // Secondary bases may provide weakrefs or dict - if (bases.length > 1 - && ((mayAddDict && !wantDict) || (mayAddWeak && !wantWeak))) { - for (PyObject base : bases) { - if (base == this.base) { - // Skip primary base - continue; - } - - if (base instanceof PyClass) { - // Classic base class provides both - if (mayAddDict && !wantDict) { - wantDict = true; - } - if (mayAddWeak && !wantWeak) { - wantWeak = true; - } - break; - } - - PyType baseType = (PyType)base; - if (mayAddDict && !wantDict && baseType.needs_userdict) { - wantDict = true; - } - if (mayAddWeak && !wantWeak && baseType.needs_weakref) { - wantWeak = true; - } - if ((!mayAddDict || wantDict) && (!mayAddWeak || wantWeak)) { - // Nothing more to check - break; - } - } - } - } - - if (wantDict) { - createDictSlot(); - } - if (wantWeak) { - createWeakrefSlot(); - } - needs_finalizer = lookup("__del__") != null; - } - - /** - * Create the __dict__ descriptor. - */ - private void createDictSlot() { - dict.__setitem__("__dict__", new PyDataDescr(this, "__dict__", PyObject.class) { - @Override - public Object invokeGet(PyObject obj) { - return obj.getDict(); - } - - @Override - public boolean implementsDescrSet() { - return true; - } - - @Override - public void invokeSet(PyObject obj, Object value) { - obj.setDict((PyObject)value); - } - - @Override - public boolean implementsDescrDelete() { - return true; - } - - @Override - public void invokeDelete(PyObject obj) { - obj.delDict(); - } - }); - needs_userdict = true; - } - - /** - * Create the __weakref__ descriptor. - */ - private void createWeakrefSlot() { - dict.__setitem__("__weakref__", new PyDataDescr(this, "__weakref__", PyObject.class) { - 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())); - } - - @Override - public Object invokeGet(PyObject obj) { - PyList weakrefs = WeakrefModule.getweakrefs(obj); - switch (weakrefs.size()) { - case 0: - return Py.None; - case 1: - return weakrefs.pyget(0); - default: - return weakrefs; - - } - } - - @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 boolean implementsDescrDelete() { - return true; - } - - @Override - public void invokeDelete(PyObject obj) { - notWritable(obj); - } - }); - needs_weakref = true; - } - - /** - * Setup this type's special attributes. - */ - private void ensureAttributes() { - inheritSpecial(); - - // special case __new__, if function => static method - PyObject new_ = dict.__finditem__("__new__"); - // XXX: java functions? - if (new_ != null && new_ instanceof PyFunction) { - dict.__setitem__("__new__", new PyStaticMethod(new_)); - } - - ensureDoc(dict); - ensureModule(dict); - - // Calculate method resolution order - mro_internal(); - fillHasSetAndDelete(); - } - - /** - * Inherit special attributes from the dominant base. - */ - private void inheritSpecial() { - if (!needs_userdict && base.needs_userdict) { - needs_userdict = true; - } - if (!needs_weakref && base.needs_weakref) { - needs_weakref = true; - } - } - - /** - * Ensure dict contains a __doc__. - * - * @param dict a PyObject mapping - */ - public static void ensureDoc(PyObject dict) { - if (dict.__finditem__("__doc__") == null) { - dict.__setitem__("__doc__", Py.None); - } - } - - /** - * Ensure dict contains a __module__, retrieving it from the current frame if it - * doesn't exist. - * - * @param dict a PyObject mapping - */ - public static void ensureModule(PyObject dict) { - if (dict.__finditem__("__module__") != null) { - return; - } - PyFrame frame = Py.getFrame(); - if (frame == null) { - return; - } - PyObject name = frame.f_globals.__finditem__("__name__"); - if (name != null) { - dict.__setitem__("__module__", name); - } - } - private static PyObject invoke_new_(PyObject new_, PyType type, boolean init, PyObject[] args, String[] keywords) { PyObject newobj; @@ -445,52 +167,7 @@ return newobj; } - /** - * Called on builtin types for a particular class. Should fill in dict, name, mro, base and - * bases from the class. - */ - protected void init(Class<?> forClass, Set<PyJavaType> needsInners) { - underlying_class = forClass; - if (underlying_class == PyObject.class) { - mro = new PyType[] {this}; - } else { - Class<?> baseClass; - if (!Py.BOOTSTRAP_TYPES.contains(underlying_class)) { - baseClass = classToBuilder.get(underlying_class).getBase(); - } else { - baseClass = PyObject.class; - } - if (baseClass == Object.class) { - baseClass = underlying_class.getSuperclass(); - } - computeLinearMro(baseClass); - } - if (Py.BOOTSTRAP_TYPES.contains(underlying_class)) { - // init will be called again from addBuilder which also removes underlying_class from - // BOOTSTRAP_TYPES - return; - } - TypeBuilder builder = classToBuilder.get(underlying_class); - name = builder.getName(); - dict = builder.getDict(this); - setIsBaseType(builder.getIsBaseType()); - instantiable = dict.__finditem__("__new__") != null; - fillHasSetAndDelete(); - } - - /** - * Fills the base and bases of this type with the type of baseClass as sets its mro to this type - * followed by the mro of baseClass. - */ - protected void computeLinearMro(Class<?> baseClass) { - base = PyType.fromClass(baseClass); - mro = new PyType[base.mro.length + 1]; - System.arraycopy(base.mro, 0, mro, 1, base.mro.length); - mro[0] = this; - bases = new PyObject[] {base}; - } - - private void fillHasSetAndDelete() { + void fillHasSetAndDelete() { has_set = lookup("__set__") != null; has_delete = lookup("__delete__") != null; } @@ -528,88 +205,6 @@ return base.getLayout(); } - /** - * 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 - * @return base Java proxy Class - * @raises Py.TypeError if multiple Java inheritance was attempted - */ - private static Class<?> getJavaLayout(PyObject[] bases, List<Class<?>> interfaces) { - Class<?> baseProxy = null; - - for (PyObject base : bases) { - if (!(base instanceof PyType)) { - continue; - } - Class<?> proxy = ((PyType)base).getProxyType(); - if (proxy == null) { - continue; - } - if (proxy.isInterface()) { - interfaces.add(proxy); - } else { - if (baseProxy != null) { - String msg = "no multiple inheritance for Java classes: %s and %s"; - throw Py.TypeError(String.format(msg, proxy.getName(), baseProxy.getName())); - } - baseProxy = proxy; - } - } - - return baseProxy; - } - - /** - * Setup the javaProxy for this type. - * - * @param baseProxyClass this type's base proxyClass - * @param interfaces a list of Java interfaces in bases - */ - private void setupProxy(Class<?> baseProxyClass, List<Class<?>> interfaces) { - if (baseProxyClass == null && interfaces.size() == 0) { - // javaProxy not applicable - return; - } - - String proxyName = name; - PyObject module = dict.__finditem__("__module__"); - if (module != null) { - proxyName = module.toString() + "$" + proxyName; - } - javaProxy = MakeProxies.makeProxy(baseProxyClass, interfaces, name, proxyName, dict); - - PyType proxyType = PyType.fromClass((Class<?>)javaProxy); - List<PyObject> cleanedBases = Generic.list(); - boolean addedProxyType = false; - for (PyObject base : bases) { - if (!(base instanceof PyType)) { - cleanedBases.add(base); - continue; - } - 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 - cleanedBases.add(base); - } else if (!addedProxyType) { - // Only add a single Java type, since everything's going to go through the - // proxy type - cleanedBases.add(proxyType); - addedProxyType = true; - } - } - } - bases = cleanedBases.toArray(new PyObject[cleanedBases.size()]); - } - //XXX: needs __doc__ @ExposedGet(name = "__base__") public PyObject getBase() { @@ -685,12 +280,7 @@ } } - private void setIsBaseType(boolean isBaseType) { - this.isBaseType = isBaseType; - tp_flags = isBaseType ? tp_flags | Py.TPFLAGS_BASETYPE : tp_flags & ~Py.TPFLAGS_BASETYPE; - } - - private void mro_internal() { + void mro_internal() { if (getType() == TYPE) { mro = computeMro(); } else { @@ -781,7 +371,7 @@ return (Class<?>)javaProxy; } - private synchronized void attachSubclass(PyType subtype) { + synchronized void attachSubclass(PyType subtype) { cleanup_subclasses(); subclasses.add(new WeakReference<PyType>(subtype, subclasses_refq)); } @@ -955,7 +545,7 @@ * @throws Py.TypeError if the bases don't all derive from the same solid_base * @throws Py.TypeError if at least one of the bases isn't a new-style class */ - private static PyType best_base(PyObject[] bases) { + static PyType best_base(PyObject[] bases) { PyType winner = null; PyType candidate = null; PyType best = null; @@ -986,17 +576,15 @@ } /** - * 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) { + private static PyType findMostDerivedMetatype(PyTuple bases, PyType initialMetatype) { PyType winner = initialMetatype; - for (PyObject base : bases_list) { + for (PyObject base : bases.asIterable()) { if (base instanceof PyClass) { continue; } @@ -1089,137 +677,13 @@ } public static void addBuilder(Class<?> forClass, TypeBuilder builder) { - if (classToBuilder == null) { - classToBuilder = Generic.map(); - } - classToBuilder.put(forClass, builder); - - if (class_to_type.containsKey(forClass)) { - if (!Py.BOOTSTRAP_TYPES.remove(forClass)) { - Py.writeWarning("init", "Bootstrapping class not in Py.BOOTSTRAP_TYPES[class=" - + forClass + "]"); - } - // The types in Py.BOOTSTRAP_TYPES are initialized before their builders are assigned, - // so do the work of addFromClass & fillFromClass after the fact - fromClass(builder.getTypeClass()).init(builder.getTypeClass(), null); - } + PyBuiltinType.addBuilder(forClass, builder); } - private static PyType addFromClass(Class<?> c, Set<PyJavaType> needsInners) { - if (ExposeAsSuperclass.class.isAssignableFrom(c)) { - PyType exposedAs = fromClass(c.getSuperclass()); - class_to_type.put(c, exposedAs); - return exposedAs; - } - return createType(c, needsInners); - } - - private static TypeBuilder getBuilder(Class<?> c) { - if (classToBuilder == null) { - // PyType itself has yet to be initialized. This should be a bootstrap type, so it'll - // go through the builder process in a second - return null; - } - 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 - return null; - } - - // 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 = classToBuilder.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 static PyType createType(Class<?> c, Set<PyJavaType> needsInners) { - PyType newtype; - if (c == PyType.class) { - newtype = new PyType(false); - } else if (Py.BOOTSTRAP_TYPES.contains(c) || getBuilder(c) != null) { - newtype = new PyType(); - } else { - newtype = new PyJavaType(); - } - - - // If filling in the type above filled the type under creation, use that one - PyType type = class_to_type.get(c); - if (type != null) { - return type; - } - - class_to_type.put(c, newtype); - newtype.builtin = true; - newtype.init(c,needsInners); - return newtype; - } - public static synchronized PyType fromClass(Class<?> c) { - if (class_to_type == null) { - class_to_type = Generic.map(); - addFromClass(PyType.class, null); - } - PyType type = class_to_type.get(c); - if (type != null) { - return type; - } - // We haven't seen this class before, so it's 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<PyJavaType> needsInners = Generic.set(); - PyType result = addFromClass(c, needsInners); - for (PyJavaType javaType : needsInners) { - Class<?> forClass = javaType.getProxyType(); - if (forClass == null) { - 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 - if (inner.getAnnotation(ExposedType.class) != null - || ExposeAsSuperclass.class.isAssignableFrom(inner)) { - Py.BOOTSTRAP_TYPES.add(inner); - } - javaType.dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner)); - } - } - } - return result; + return PyBuiltinType.fromClass(c); } - static PyType fromClassSkippingInners(Class<?> c, Set<PyJavaType> needsInners) { - PyType type = class_to_type.get(c); - if (type != null) { - return type; - } - return addFromClass(c, needsInners); - } - @ExposedMethod(doc = BuiltinDocs.type___getattribute___doc) final PyObject type___getattribute__(PyObject name) { String n = asName(name); @@ -1535,46 +999,6 @@ fastGetName(), name)); } - //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())); - } else if (obj instanceof PyUnicode) { - 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) != '_')) { - throw Py.TypeError(msg); - } - for (char c : identifier.toCharArray()) { - if (!Character.isLetterOrDigit(c) && c != '_') { - throw Py.TypeError(msg); - } - } - return identifier; - } - - //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 - int i = 0; - while (classname.charAt(i) == '_') { - i++; - } - return ("_" + classname.substring(i) + methodname).intern(); - } - return methodname; - } - /** Used when serializing this type. */ protected Object writeReplace() { return new TypeResolver(underlying_class, getModule().toString(), getName()); Deleted: branches/customizable-proxymaker/src/org/python/core/PyTypeDerived.java =================================================================== --- branches/customizable-proxymaker/src/org/python/core/PyTypeDerived.java 2009-08-22 07:46:25 UTC (rev 6702) +++ branches/customizable-proxymaker/src/org/python/core/PyTypeDerived.java 2009-08-22 07:53:18 UTC (rev 6703) @@ -1,1138 +0,0 @@ -/* Generated file, do not modify. See jython/src/templates/gderived.py. */ -package org.python.core; - -import java.io.Serializable; - -public class PyTypeDerived extends PyType implements Slotted { - - public PyObject getSlot(int index) { - return slots[index]; - } - - public void setSlot(int index,PyObject value) { - slots[index]=value; - } - - private PyObject[]slots; - - public PyTypeDerived(PyType subtype) { - super(subtype); - slots=new PyObject[subtype.getNumSlots()]; - } - - public PyString __str__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__str__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(); - if (res instanceof PyString) - return(PyString)res; - throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); - } - return super.__str__(); - } - - public PyString __repr__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__repr__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(); - if (res instanceof PyString) - return(PyString)res; - throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); - } - return super.__repr__(); - } - - public PyString __hex__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__hex__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(); - if (res instanceof PyString) - return(PyString)res; - throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); - } - return super.__hex__(); - } - - public PyString __oct__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__oct__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(); - if (res instanceof PyString) - return(PyString)res; - throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); - } - return super.__oct__(); - } - - public PyFloat __float__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__float__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(); - if (res instanceof PyFloat) - return(PyFloat)res; - throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); - } - return super.__float__(); - } - - public PyComplex __complex__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__complex__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(); - if (res instanceof PyComplex) - return(PyComplex)res; - throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); - } - return super.__complex__(); - } - - public PyObject __pos__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__pos__"); - if (impl!=null) - return impl.__get__(this,self_type).__call__(); - return super.__pos__(); - } - - public PyObject __neg__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__neg__"); - if (impl!=null) - return impl.__get__(this,self_type).__call__(); - return super.__neg__(); - } - - public PyObject __abs__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__abs__"); - if (impl!=null) - return impl.__get__(this,self_type).__call__(); - return super.__abs__(); - } - - public PyObject __invert__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__invert__"); - if (impl!=null) - return impl.__get__(this,self_type).__call__(); - return super.__invert__(); - } - - public PyObject __reduce__() { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__reduce__"); - if (impl!=null) - return impl.__get__(this,self_type).__call__(); - return super.__reduce__(); - } - - public PyObject __add__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__add__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__add__(other); - } - - public PyObject __radd__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__radd__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__radd__(other); - } - - public PyObject __sub__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__sub__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__sub__(other); - } - - public PyObject __rsub__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rsub__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rsub__(other); - } - - public PyObject __mul__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__mul__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__mul__(other); - } - - public PyObject __rmul__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rmul__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rmul__(other); - } - - public PyObject __div__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__div__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__div__(other); - } - - public PyObject __rdiv__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rdiv__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rdiv__(other); - } - - public PyObject __floordiv__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__floordiv__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__floordiv__(other); - } - - public PyObject __rfloordiv__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rfloordiv__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rfloordiv__(other); - } - - public PyObject __truediv__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__truediv__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__truediv__(other); - } - - public PyObject __rtruediv__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rtruediv__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rtruediv__(other); - } - - public PyObject __mod__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__mod__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__mod__(other); - } - - public PyObject __rmod__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rmod__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rmod__(other); - } - - public PyObject __divmod__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__divmod__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__divmod__(other); - } - - public PyObject __rdivmod__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rdivmod__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rdivmod__(other); - } - - public PyObject __rpow__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rpow__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rpow__(other); - } - - public PyObject __lshift__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__lshift__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__lshift__(other); - } - - public PyObject __rlshift__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rlshift__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rlshift__(other); - } - - public PyObject __rshift__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rshift__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rshift__(other); - } - - public PyObject __rrshift__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rrshift__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rrshift__(other); - } - - public PyObject __and__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__and__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__and__(other); - } - - public PyObject __rand__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rand__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rand__(other); - } - - public PyObject __or__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__or__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__or__(other); - } - - public PyObject __ror__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__ror__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__ror__(other); - } - - public PyObject __xor__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__xor__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__xor__(other); - } - - public PyObject __rxor__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__rxor__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__rxor__(other); - } - - public PyObject __lt__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__lt__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__lt__(other); - } - - public PyObject __le__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__le__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__le__(other); - } - - public PyObject __gt__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__gt__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__gt__(other); - } - - public PyObject __ge__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__ge__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__ge__(other); - } - - public PyObject __eq__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__eq__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__eq__(other); - } - - public PyObject __ne__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__ne__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__ne__(other); - } - - public PyObject __iadd__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__iadd__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__iadd__(other); - } - - public PyObject __isub__(PyObject other) { - PyType self_type=getType(); - PyObject impl=self_type.lookup("__isub__"); - if (impl!=null) { - PyObject res=impl.__get__(this,self_type).__call__(other); - if (res==Py.NotImplemented) - return null; - return res; - } - return super.__isub__(other)... [truncated message content] |
From: <cg...@us...> - 2009-08-22 07:46:31
|
Revision: 6702 http://jython.svn.sourceforge.net/jython/?rev=6702&view=rev Author: cgroves Date: 2009-08-22 07:46:25 +0000 (Sat, 22 Aug 2009) Log Message: ----------- Branching to keep out of 2.5.1's hair Added Paths: ----------- branches/customizable-proxymaker/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-21 23:55:20
|
Revision: 6701 http://jython.svn.sourceforge.net/jython/?rev=6701&view=rev Author: wmeissner Date: 2009-08-21 23:55:10 +0000 (Fri, 21 Aug 2009) Log Message: ----------- New branch for ctypes implemented via jffi Added Paths: ----------- branches/ctypes-jffi/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-21 23:50:52
|
Revision: 6700 http://jython.svn.sourceforge.net/jython/?rev=6700&view=rev Author: wmeissner Date: 2009-08-21 23:50:46 +0000 (Fri, 21 Aug 2009) Log Message: ----------- Delete incorrect branch Removed Paths: ------------- branches/ctypes-jffi/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-21 23:42:57
|
Revision: 6699 http://jython.svn.sourceforge.net/jython/?rev=6699&view=rev Author: wmeissner Date: 2009-08-21 23:42:49 +0000 (Fri, 21 Aug 2009) Log Message: ----------- New branch for ctypes implemented via jffi Added Paths: ----------- branches/ctypes-jffi/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |