From: <cg...@us...> - 2009-01-18 10:04:32
|
Revision: 5945 http://jython.svn.sourceforge.net/jython/?rev=5945&view=rev Author: cgroves Date: 2009-01-18 10:04:29 +0000 (Sun, 18 Jan 2009) Log Message: ----------- Add an Ant task to compile .py files to $py.class. It runs on Lib as part of developer-build to exercise it a little bit. Also, only rename the xerces parts of org.apache. Otherwise our ant imports get renamed when jarjaring. Modified Paths: -------------- trunk/jython/build.xml trunk/jython/src/org/python/compiler/Future.java trunk/jython/src/org/python/compiler/Module.java trunk/jython/src/org/python/compiler/ScopesCompiler.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/imp.java trunk/jython/src/org/python/expose/generate/ExposeTask.java trunk/jython/src/org/python/modules/_py_compile.java Added Paths: ----------- trunk/jython/src/org/python/util/GlobMatchingTask.java trunk/jython/src/org/python/util/JycompileAntTask.java Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/build.xml 2009-01-18 10:04:29 UTC (rev 5945) @@ -101,9 +101,9 @@ </echo> </target> - <target name="jarless" depends="compile, copy-lib"/> + <target name="jarless" depends="compile, pycompile"/> - <target name="developer-build" depends="prepare-output, jar, copy-lib" description="a local build for developers" /> + <target name="developer-build" depends="prepare-output, pycompile" description="a local build for developers" /> <target name="full-build" depends="full-check, install" description="a full build with svn checkout" /> @@ -364,7 +364,7 @@ <!-- skip-brand can be set in ant.properties or as a system property to keep from updating the version.properties file and making the jar on every developer build. --> - <target name="brand-version" depends="version-init, svnversion" unless="skip-brand"> + <target name="brand-version" depends="init, svnversion" unless="skip-brand"> <condition property="build.svn.revision" value=""> <not> <isset property="build.svn.revision"/> @@ -522,8 +522,10 @@ <rule pattern="org.jruby.ext.posix.**" result="org.python.posix.@1"/> <zipfileset src="extlibs/constantine-0.4.jar"/> <rule pattern="com.kenai.constantine.**" result="org.python.constantine.@1"/> - <zipfileset src="extlibs/xercesImpl-2.9.1.jar"/> - <rule pattern="org.apache.**" result="org.python.apache.@1"/> + <rule pattern="org.apache.xml.**" result="org.python.apache.xml.@1"/> + <rule pattern="org.apache.xerces.**" result="org.python.apache.xerces.@1"/> + <rule pattern="org.apache.wml.**" result="org.python.apache.wml.@1"/> + <rule pattern="org.apache.html.**" result="org.python.apache.html.@1"/> <manifest> <attribute name="Main-Class" value="org.python.util.jython" /> <attribute name="Built-By" value="${user.name}" /> @@ -637,6 +639,15 @@ </copy> </target> + <target name="pycompile" depends="jar,copy-lib"> + <taskdef name="jycompile" classname="org.python.util.JycompileAntTask"> + <classpath path="${dist.dir}/Lib"/> + <classpath path="${dist.dir}/${jython.dev.jar}" /> + <classpath refid="main.classpath" /> + </taskdef> + <jycompile srcdir="${dist.dir}/Lib" destdir="${dist.dir}/Lib" excludes="test/**"/> + </target> + <target name="copy-lib" depends="init, copy-javalib, copy-cpythonlib"> <!-- XXX untested and most likely broken in 2.5 <copy todir="${dist.dir}" preservelastmodified="true"> Modified: trunk/jython/src/org/python/compiler/Future.java =================================================================== --- trunk/jython/src/org/python/compiler/Future.java 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/src/org/python/compiler/Future.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -26,8 +26,7 @@ return false; int n = cand.getInternalNames().size(); if (n == 0) { - throw new ParseException( - "future statement does not support import *",cand); + throw new ParseException("future statement does not support import *", cand); } for (int i = 0; i < n; i++) { String feature = cand.getInternalNames().get(i).getInternalName(); @@ -56,8 +55,7 @@ if (feature.equals("GIL") || feature.equals("global_interpreter_lock")) { throw new ParseException("Never going to happen!", cand); } - throw new ParseException("future feature "+feature+ - " is not defined",cand); + throw new ParseException("future feature " + feature + " is not defined", cand); } return true; } @@ -90,7 +88,7 @@ if (!(s instanceof ImportFrom)) break; s.from_future_checked = true; - if (!check((ImportFrom) s)) + if (!check((ImportFrom)s)) break; } @@ -119,7 +117,7 @@ public boolean areDivisionOn() { return division; } - + public boolean withStatementSupported() { return with_statement; } Modified: trunk/jython/src/org/python/compiler/Module.java =================================================================== --- trunk/jython/src/org/python/compiler/Module.java 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/src/org/python/compiler/Module.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -435,12 +435,12 @@ c.invokevirtual("org/python/core/PyFrame", "getname_or_null", "(" + $str + ")" + $pyObj); c.dup(); c.ifnonnull(label_got_name); - + c.pop(); c.aload(1); c.ldc("__name__"); c.invokevirtual("org/python/core/PyFrame", "getname_or_null", "(" + $str + ")" + $pyObj); - + c.label(label_got_name); c.astore(module_tmp); c.aload(1); @@ -448,7 +448,7 @@ c.aload(module_tmp); c.invokevirtual("org/python/core/PyFrame", "setlocal", "(" + $str + $pyObj + ")V"); } - + Label genswitch = new Label(); if (scope.generator) { c.goto_(genswitch); @@ -476,13 +476,13 @@ compiler.parse(tree, c, fast_locals, className, classBody, scope, cflags); - + // similar to visitResume code in pyasm.py if (scope.generator) { c.label(genswitch); - + c.aload(1); - c.getfield("org/python/core/PyFrame", "f_lasti", "I"); + c.getfield("org/python/core/PyFrame", "f_lasti", "I"); Label[] yields = new Label[compiler.yields.size()+1]; yields[0] = start; @@ -637,7 +637,7 @@ public static void compile(mod node, OutputStream ostream, String name, String filename, boolean linenumbers, boolean printResults, - org.python.core.CompilerFlags cflags) + CompilerFlags cflags) throws Exception { Module module = new Module(name, filename, linenumbers); Modified: trunk/jython/src/org/python/compiler/ScopesCompiler.java =================================================================== --- trunk/jython/src/org/python/compiler/ScopesCompiler.java 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/src/org/python/compiler/ScopesCompiler.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -19,11 +19,11 @@ import org.python.antlr.ast.Return; import org.python.antlr.ast.With; import org.python.antlr.ast.Yield; -import org.python.antlr.ast.comprehension; import org.python.antlr.ast.arguments; import org.python.antlr.ast.expr_contextType; import org.python.antlr.base.expr; import org.python.antlr.base.stmt; +import org.python.core.ParserFacade; import java.util.ArrayList; import java.util.Hashtable; @@ -85,8 +85,7 @@ try { visit(node); } catch (Throwable t) { - throw org.python.core.ParserFacade.fixParseError(null, t, - code_compiler.getFilename()); + throw ParserFacade.fixParseError(null, t, code_compiler.getFilename()); } } @@ -138,10 +137,10 @@ beginScope(node.getInternalName(), FUNCSCOPE, node, ac); int n = ac.names.size(); for (int i = 0; i < n; i++) { - cur.addParam((String) ac.names.get(i)); + cur.addParam(ac.names.get(i)); } for (int i = 0; i < ac.init_code.size(); i++) { - visit((stmt) ac.init_code.get(i)); + visit(ac.init_code.get(i)); } cur.markFromParam(); suite(node.getInternalBody()); @@ -291,7 +290,7 @@ traverse(node); return null; } - + @Override public Object visitReturn(Return node) throws Exception { if (node.getInternalValue() != null) { Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/src/org/python/core/PySystemState.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -495,23 +495,23 @@ jarIndex = lowerCaseClasspath.indexOf(JYTHON_DEV_JAR); } if (jarIndex >= 0) { - int start = classpath.lastIndexOf(java.io.File.pathSeparator, jarIndex) + 1; + int start = classpath.lastIndexOf(File.pathSeparator, jarIndex) + 1; root = classpath.substring(start, jarIndex); } else { // in case JYTHON_JAR is referenced from a MANIFEST inside another jar on the classpath - root = jarFileName; + root = new File(jarFileName).getParent(); } } } - if (root != null) { - File rootFile = new File(root); - try { - root = rootFile.getCanonicalPath(); - } catch (IOException ioe) { - root = rootFile.getAbsolutePath(); - } + if (root == null) { + return null; } - return root; + File rootFile = new File(root); + try { + return rootFile.getCanonicalPath(); + } catch (IOException ioe) { + return rootFile.getAbsolutePath(); + } } public static void determinePlatform(Properties props) { @@ -554,8 +554,7 @@ } try { addRegistryFile(new File(prefix, "registry")); - File homeFile = new File(registry.getProperty("user.home"), - ".jython"); + File homeFile = new File(registry.getProperty("user.home"), ".jython"); addRegistryFile(homeFile); } catch (Exception exc) { } @@ -615,21 +614,23 @@ } public static synchronized void initialize() { - initialize(null, null, new String[] {""}); + initialize(null, null); } + public static synchronized void initialize(Properties preProperties, Properties postProperties) { + initialize(preProperties, postProperties, new String[] {""}); + } + public static synchronized void initialize(Properties preProperties, Properties postProperties, - String[] argv) - { + String[] argv) { initialize(preProperties, postProperties, argv, null); } public static synchronized void initialize(Properties preProperties, Properties postProperties, String[] argv, - ClassLoader classLoader) - { + ClassLoader classLoader) { initialize(preProperties, postProperties, argv, classLoader, new ClassicPyObjectAdapter()); } Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/src/org/python/core/imp.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -133,6 +133,14 @@ return data; } + public static byte[] compileSource(String name, File file) { + return compileSource(name, file, null); + } + + public static byte[] compileSource(String name, File file, String sourceFilename) { + return compileSource(name, file, sourceFilename, null); + } + public static byte[] compileSource(String name, File file, String sourceFilename, String compiledFilename) { if (sourceFilename == null) { @@ -209,8 +217,7 @@ } } - public static PyObject createFromSource(String name, InputStream fp, - String filename) { + public static PyObject createFromSource(String name, InputStream fp, String filename) { return createFromSource(name, fp, filename, null); } Modified: trunk/jython/src/org/python/expose/generate/ExposeTask.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposeTask.java 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/src/org/python/expose/generate/ExposeTask.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -7,93 +7,44 @@ 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; import org.objectweb.asm.ClassWriter; -import org.python.util.Generic; +import org.python.util.GlobMatchingTask; -public class ExposeTask extends MatchingTask { +public class ExposeTask extends GlobMatchingTask { - private Path src; - - private 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); - } + @Override + protected String getFrom() { + return "*.class"; } - /** - * Gets the source dirs to find the class files to be exposed. - */ - public Path getSrcdir() { - return src; + @Override + protected String getTo() { + return "*.class"; } - /** - * 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 - // documentation inherited - 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); - } - if(toExpose.size() > 1) { + public void process(Set<File> toExpose) throws BuildException { + if (toExpose.size() > 1) { log("Exposing " + toExpose.size() + " classes"); - } else if(toExpose.size() == 1) { + } else if (toExpose.size() == 1) { log("Exposing 1 class"); } - for(File f : toExpose) { + for (File f : toExpose) { ExposedTypeProcessor etp; try { etp = new ExposedTypeProcessor(new FileInputStream(f)); - } catch(IOException e) { + } catch (IOException e) { throw new BuildException("Unable to read '" + f + "' to expose it", e); - } catch(InvalidExposingException iee) { + } catch (InvalidExposingException iee) { throw new BuildException(iee.getMessage()); } - for(MethodExposer exposer : etp.getMethodExposers()) { + for (MethodExposer exposer : etp.getMethodExposers()) { generate(exposer); } - for(DescriptorExposer exposer : etp.getDescriptorExposers()) { + for (DescriptorExposer exposer : etp.getDescriptorExposers()) { generate(exposer); } - if(etp.getNewExposer() != null) { + if (etp.getNewExposer() != null) { generate(etp.getNewExposer()); } generate(etp.getTypeExposer()); @@ -114,39 +65,16 @@ try { out = new FileOutputStream(dest); out.write(newClassfile); - } catch(IOException e) { + } catch (IOException e) { throw new BuildException("Unable to write to '" + dest + "'", e); } finally { - if(out != null) { + if (out != null) { try { out.close(); - } catch(IOException e) { + } catch (IOException e) { // Le sigh... } } } } - - protected void scanDir(File srcDir, File destDir, String[] files) { - GlobPatternMapper m = new GlobPatternMapper(); - m.setFrom("*.class"); - m.setTo("*.class"); - 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()); - } - } } Modified: trunk/jython/src/org/python/modules/_py_compile.java =================================================================== --- trunk/jython/src/org/python/modules/_py_compile.java 2009-01-18 00:53:10 UTC (rev 5944) +++ trunk/jython/src/org/python/modules/_py_compile.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -13,41 +13,46 @@ public static PyList __all__ = new PyList(new PyString[] { new PyString("compile") }); public static boolean compile(String filename, String cfile, String dfile) { - // Resolve relative path names. dfile is only used for error - // messages and should not be resolved + // Resolve relative path names. dfile is only used for error messages and should not be + // resolved PySystemState sys = Py.getSystemState(); filename = sys.getPath(filename); cfile = sys.getPath(cfile); - + File file = new File(filename); if (!file.exists()) { throw Py.IOError(Errno.ENOENT, filename); } - String name = file.getName(); + String name = getModuleName(file); + + byte[] bytes = org.python.core.imp.compileSource(name, file, dfile, cfile); + org.python.core.imp.cacheCompiledSource(filename, cfile, bytes); + + return bytes.length > 0; + } + + public static final String getModuleName(File f) { + String name = f.getName(); int dot = name.lastIndexOf('.'); if (dot != -1) { name = name.substring(0, dot); } // name the __init__ module after its package - File dir = file.getParentFile(); - if (dir != null && name.equals("__init__")) { + File dir = f.getParentFile(); + if (name.equals("__init__")) { name = dir.getName(); dir = dir.getParentFile(); } - // Make the compiled classfile's name the fully qualified with a package by - // walking up the directory tree looking for __init__.py files. Don't - // check for __init__$py.class since we're compiling source here and the - // existence of a class file without corresponding source probably doesn't - // indicate a package. + // Make the compiled classfile's name fully qualified with a package by walking up the + // directory tree looking for __init__.py files. Don't check for __init__$py.class since + // we're compiling source here and the existence of a class file without corresponding + // source probably doesn't indicate a package. while (dir != null && (new File(dir, "__init__.py").exists())) { name = dir.getName() + "." + name; dir = dir.getParentFile(); } - byte[] bytes = org.python.core.imp.compileSource(name, file, dfile, cfile); - org.python.core.imp.cacheCompiledSource(filename, cfile, bytes); - - return bytes.length > 0; + return name; } } Added: trunk/jython/src/org/python/util/GlobMatchingTask.java =================================================================== --- trunk/jython/src/org/python/util/GlobMatchingTask.java (rev 0) +++ trunk/jython/src/org/python/util/GlobMatchingTask.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -0,0 +1,101 @@ +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.GlobPatternMapper; +import org.apache.tools.ant.util.SourceFileScanner; + +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 + 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 Added: trunk/jython/src/org/python/util/JycompileAntTask.java =================================================================== --- trunk/jython/src/org/python/util/JycompileAntTask.java (rev 0) +++ trunk/jython/src/org/python/util/JycompileAntTask.java 2009-01-18 10:04:29 UTC (rev 5945) @@ -0,0 +1,56 @@ +package org.python.util; + +import java.io.File; +import java.util.Properties; +import java.util.Set; + +import org.apache.tools.ant.BuildException; +import org.python.core.PyException; +import org.python.core.PySystemState; +import org.python.core.imp; +import org.python.modules._py_compile; + +public class JycompileAntTask extends GlobMatchingTask { + + @Override + public void process(Set<File> toCompile) throws BuildException { + if (toCompile.size() == 0) { + return; + } else if (toCompile.size() > 1) { + log("Compiling " + toCompile.size() + " files"); + } else if (toCompile.size() == 1) { + log("Compiling 1 file"); + } + Properties props = new Properties(); + props.setProperty(PySystemState.PYTHON_CACHEDIR_SKIP, "true"); + PySystemState.initialize(System.getProperties(), props); + for (File src : toCompile) { + String name = _py_compile.getModuleName(src); + String compiledFilePath = name.replace('.', '/'); + if (src.getName().endsWith("__init__.py")) { + compiledFilePath += "/__init__"; + } + File compiled = new File(destDir, compiledFilePath + "$py.class"); + byte[] bytes; + try { + bytes = imp.compileSource(name, src); + } catch (PyException pye) { + pye.printStackTrace(); + throw new BuildException("Compile failed; see the compiler error output for details."); + } + File dir = compiled.getParentFile(); + if (!dir.exists() && !compiled.getParentFile().mkdirs()) { + throw new BuildException("Unable to make directory for compiled file: " + compiled); + } + imp.cacheCompiledSource(src.getAbsolutePath(), compiled.getAbsolutePath(), bytes); + } + } + + protected String getFrom() { + return "*.py"; + } + + 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-01-21 23:32:59
|
Revision: 5955 http://jython.svn.sourceforge.net/jython/?rev=5955&view=rev Author: cgroves Date: 2009-01-21 23:32:55 +0000 (Wed, 21 Jan 2009) Log Message: ----------- Add a jython initializer service. If META-INF/services/org.python.core.JythonInitializer is on the classpath, the class named in that file will be instantiated and used in Jython's initialization. This is useful when Jython is initialized by a library outside of your control, but some customization still needs to be done to Jython's environment. I promise not to add a JythonFactory or a JythonFactoryFactory. Modified Paths: -------------- trunk/jython/build.xml trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/ThreadStateMapping.java Added Paths: ----------- trunk/jython/Lib/test/check_for_initializer_in_syspath.py trunk/jython/Lib/test/test_jython_initializer.py trunk/jython/src/org/python/core/JythonInitializer.java trunk/jython/tests/data/ trunk/jython/tests/data/initializer/ trunk/jython/tests/data/initializer/META-INF/ trunk/jython/tests/data/initializer/META-INF/services/ trunk/jython/tests/data/initializer/META-INF/services/org.python.core.JythonInitializer trunk/jython/tests/data/initializer/SyspathAppendingInitializer.java Added: trunk/jython/Lib/test/check_for_initializer_in_syspath.py =================================================================== --- trunk/jython/Lib/test/check_for_initializer_in_syspath.py (rev 0) +++ trunk/jython/Lib/test/check_for_initializer_in_syspath.py 2009-01-21 23:32:55 UTC (rev 5955) @@ -0,0 +1,2 @@ +import sys +assert "/from_SyspathAppendingInitializer_with_love" in sys.path Added: trunk/jython/Lib/test/test_jython_initializer.py =================================================================== --- trunk/jython/Lib/test/test_jython_initializer.py (rev 0) +++ trunk/jython/Lib/test/test_jython_initializer.py 2009-01-21 23:32:55 UTC (rev 5955) @@ -0,0 +1,17 @@ +import unittest +import subprocess +import sys +from test import test_support + +class TestUsingInitializer(unittest.TestCase): + def test_syspath_initializer(self): + fn = test_support.findfile("check_for_initializer_in_syspath.py") + ret = subprocess.Popen([sys.executable, fn], + env={"CLASSPATH":"tests/data/initializer"}).wait() + self.assertEquals(0, ret) + +def test_main(): + test_support.run_unittest(TestUsingInitializer) + +if __name__ == "__main__": + test_main() Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-01-21 21:26:50 UTC (rev 5954) +++ trunk/jython/build.xml 2009-01-21 23:32:55 UTC (rev 5955) @@ -482,7 +482,17 @@ nowarn="${nowarn}"> <classpath refid="test.classpath" /> </javac> + <javac srcdir="tests/data/initializer" + destdir="tests/data/initializer" + target="${jdk.target.version}" + source="${jdk.source.version}" + debug="${debug}" + deprecation="${deprecation}" + nowarn="${nowarn}"> + <classpath refid="test.classpath" /> + </javac> + <copy file="${source.dir}/org/python/modules/ucnhash.dat" todir="${compile.dir}/org/python/modules" preservelastmodified="true" /> Added: trunk/jython/src/org/python/core/JythonInitializer.java =================================================================== --- trunk/jython/src/org/python/core/JythonInitializer.java (rev 0) +++ trunk/jython/src/org/python/core/JythonInitializer.java 2009-01-21 23:32:55 UTC (rev 5955) @@ -0,0 +1,35 @@ +package org.python.core; + +import java.util.Properties; + +import org.python.core.adapter.ExtensiblePyObjectAdapter; + +/** + * A service for initializing Jython without explicitly calling {@link PySystemState#initialize}. If + * a file META-INF/services/org.python.core.JythonInitializer is on the classpath, Jython will + * instantiate the class named in that file and use it in Jython's initialization. The given class + * must be an implementation of this interface with a no-arg constructor. + * + * @see <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">Java + Service Providers</a> + */ +public interface JythonInitializer { + + /** + * Called from {@link PySystemState#initialize} with the full set of initialization arguments. + * Implementations may modify or replace the given arguments, and must call + * {@link PySystemState#doInitialize}. + * + * @param argv + * - The command line arguments the jython interpreter was started with, or an empty + * array if jython wasn't started directly from the command line. + * @param classLoader + * - The classloader to be used by sys, or null if no sys-specific classloader was + * specified + */ + void initialize(Properties preProperties, + Properties postProperties, + String[] argv, + ClassLoader classLoader, + ExtensiblePyObjectAdapter adapter); +} Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2009-01-21 21:26:50 UTC (rev 5954) +++ trunk/jython/src/org/python/core/PySystemState.java 2009-01-21 23:32:55 UTC (rev 5955) @@ -1,11 +1,16 @@ // Copyright (c) Corporation for National Research Initiatives package org.python.core; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.net.URL; import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; import java.security.AccessControlException; import java.util.Map; import java.util.Properties; @@ -539,9 +544,6 @@ Py.writeError("systemState", "trying to reinitialize registry"); return; } - if (preProperties == null) { - preProperties = getBaseProperties(); - } registry = preProperties; String prefix = findRoot(preProperties, postProperties, jarFileName); @@ -572,9 +574,7 @@ } } catch (SecurityException e) { } - if (postProperties != null) { - registry.putAll(postProperties); - } + registry.putAll(postProperties); if (standalone) { // set default standalone property (if not yet set) if (!registry.containsKey(PYTHON_CACHEDIR_SKIP)) { @@ -642,6 +642,116 @@ if (initialized) { return; } + if (preProperties == null) { + preProperties = getBaseProperties(); + } + if (postProperties == null) { + postProperties = new Properties(); + } + try { + ClassLoader context = Thread.currentThread().getContextClassLoader(); + if (context != null) { + if (initialize(preProperties, postProperties, argv, classLoader, adapter, context)) { + return; + } + } else { + Py.writeDebug("initializer", "Context class loader null, skipping"); + } + ClassLoader sysStateLoader = PySystemState.class.getClassLoader(); + if (sysStateLoader != null) { + if (initialize(preProperties, + postProperties, + argv, + classLoader, + adapter, + sysStateLoader)) { + return; + } + } else { + Py.writeDebug("initializer", "PySystemState.class class loader null, skipping"); + } + } catch (UnsupportedCharsetException e) { + Py.writeWarning("initializer", "Unable to load the UTF-8 charset to read an initializer definition"); + e.printStackTrace(System.err); + } catch (SecurityException e) { + // Must be running in a security environment that doesn't allow access to the class + // loader + } catch (Exception e) { + Py.writeWarning("initializer", + "Unexpected exception thrown while trying to use initializer service"); + e.printStackTrace(System.err); + } + doInitialize(preProperties, postProperties, argv, classLoader, adapter); + } + + private static final String INITIALIZER_SERVICE = + "META-INF/services/org.python.core.JythonInitializer"; + + /** + * Attempts to read a SystemStateInitializer service from the given classloader, instantiate it, + * and initialize with it. + * + * @throws UnsupportedCharsetException + * if unable to load UTF-8 to read a service definition + * @return true if a service is found and successfully initializes. + */ + private static boolean initialize(Properties pre, + Properties post, + String[] argv, + ClassLoader sysClassLoader, + ExtensiblePyObjectAdapter adapter, + ClassLoader initializerClassLoader) { + InputStream in = initializerClassLoader.getResourceAsStream(INITIALIZER_SERVICE); + if (in == null) { + Py.writeDebug("initializer", "'" + INITIALIZER_SERVICE + "' not found on " + initializerClassLoader); + return false; + } + BufferedReader r = new BufferedReader(new InputStreamReader(in, Charset.forName("UTF-8"))); + String className; + try { + className = r.readLine(); + } catch (IOException e) { + Py.writeWarning("initializer", "Failed reading '" + INITIALIZER_SERVICE + "' from " + + initializerClassLoader); + e.printStackTrace(System.err); + return false; + } + Class<?> initializer; + try { + initializer = initializerClassLoader.loadClass(className); + } catch (ClassNotFoundException e) { + Py.writeWarning("initializer", "Specified initializer class '" + className + + "' not found, continuing"); + return false; + } + try { + ((JythonInitializer)initializer.newInstance()).initialize(pre, + post, + argv, + sysClassLoader, + adapter); + } catch (Exception e) { + Py.writeWarning("initializer", "Failed initializing with class '" + className + + "', continuing"); + e.printStackTrace(System.err); + return false; + } + if (!initialized) { + Py.writeWarning("initializer", "Initializer '" + className + + "' failed to call doInitialize, using default initialization"); + } + return initialized; + } + + + public static synchronized PySystemState doInitialize(Properties preProperties, + Properties postProperties, + String[] argv, + ClassLoader classLoader, + ExtensiblePyObjectAdapter adapter) { + if (initialized) { + return Py.defaultSystemState; + } initialized = true; Py.setAdapter(adapter); boolean standalone = false; @@ -663,11 +773,13 @@ // Finish up standard Python initialization... Py.defaultSystemState = new PySystemState(); Py.setSystemState(Py.defaultSystemState); - if (classLoader != null) + if (classLoader != null) { Py.defaultSystemState.setClassLoader(classLoader); + } Py.initClassExceptions(getDefaultBuiltins()); // Make sure that Exception classes have been loaded new PySyntaxError("", 1, 1, "", ""); + return Py.defaultSystemState; } private static void initStaticFields() { Modified: trunk/jython/src/org/python/core/ThreadStateMapping.java =================================================================== --- trunk/jython/src/org/python/core/ThreadStateMapping.java 2009-01-21 21:26:50 UTC (rev 5954) +++ trunk/jython/src/org/python/core/ThreadStateMapping.java 2009-01-21 23:32:55 UTC (rev 5955) @@ -9,10 +9,13 @@ return ts; } + Thread t = Thread.currentThread(); - if (newSystemState == null) { Py.writeDebug("threadstate", "no current system state"); + if (Py.defaultSystemState == null) { + PySystemState.initialize(); + } newSystemState = Py.defaultSystemState; } Property changes on: trunk/jython/tests/data/initializer ___________________________________________________________________ Added: svn:ignore + SyspathAppendingInitializer.class Added: trunk/jython/tests/data/initializer/META-INF/services/org.python.core.JythonInitializer =================================================================== --- trunk/jython/tests/data/initializer/META-INF/services/org.python.core.JythonInitializer (rev 0) +++ trunk/jython/tests/data/initializer/META-INF/services/org.python.core.JythonInitializer 2009-01-21 23:32:55 UTC (rev 5955) @@ -0,0 +1 @@ +SyspathAppendingInitializer Added: trunk/jython/tests/data/initializer/SyspathAppendingInitializer.java =================================================================== --- trunk/jython/tests/data/initializer/SyspathAppendingInitializer.java (rev 0) +++ trunk/jython/tests/data/initializer/SyspathAppendingInitializer.java 2009-01-21 23:32:55 UTC (rev 5955) @@ -0,0 +1,18 @@ +import java.util.Properties; +import org.python.core.JythonInitializer; +import org.python.core.Py; +import org.python.core.PySystemState; +import org.python.core.adapter.ExtensiblePyObjectAdapter; + +public class SyspathAppendingInitializer implements JythonInitializer { + public void initialize(Properties preProperties, + Properties postProperties, + String[] argv, + ClassLoader classLoader, + ExtensiblePyObjectAdapter adapter) { + postProperties.put(PySystemState.PYTHON_CACHEDIR_SKIP, "true"); + PySystemState defaultState = + PySystemState.doInitialize(preProperties, postProperties, argv, classLoader, adapter); + defaultState.path.append(Py.newString("/from_SyspathAppendingInitializer_with_love")); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-22 02:21:14
|
Revision: 5956 http://jython.svn.sourceforge.net/jython/?rev=5956&view=rev Author: fwierzbicki Date: 2009-01-22 02:21:08 +0000 (Thu, 22 Jan 2009) Log Message: ----------- Fix for http://bugs.jython.org/issue1239. When jars where added to sys.path, they did not always trigger package caching, leading to unexpected import failures. This is Charlie Grove's fix, which was much better than mine. Modified Paths: -------------- trunk/jython/Lib/test/test_classpathimporter.py trunk/jython/src/org/python/core/SyspathJavaLoader.java trunk/jython/src/org/python/core/imp.java Added Paths: ----------- trunk/jython/Lib/test/bug1239.jar Added: trunk/jython/Lib/test/bug1239.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/Lib/test/bug1239.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/jython/Lib/test/test_classpathimporter.py =================================================================== --- trunk/jython/Lib/test/test_classpathimporter.py 2009-01-21 23:32:55 UTC (rev 5955) +++ trunk/jython/Lib/test/test_classpathimporter.py 2009-01-22 02:21:08 UTC (rev 5956) @@ -37,6 +37,17 @@ sys.path = ['__pyclasspath__/Lib'] self.setClassLoaderAndCheck("classimport_Lib.jar", "__pyclasspath__/Lib") + # I don't like the checked in jar file bug1239.jar. The *one* thing I + # liked about the tests in bugtests/ is that you could create a java file, + # compile it, jar it and destroy the jar when done. Maybe when we move to + # JDK 6 and can use JSR-199 to do runtime compiling, we can go back to + # that. Anyway, see http://bugs.jython.org/issue1239. In short, jars added + # with sys.path.append where not getting scanned if they start with a top + # level package we already have, like the "org" in org.python.* + def test_bug1239(self): + sys.path.append("Lib/test/bug1239.jar") + import org.test403javapackage.test403 + def test_main(): test_support.run_unittest(ClasspathImporterTestCase) Modified: trunk/jython/src/org/python/core/SyspathJavaLoader.java =================================================================== --- trunk/jython/src/org/python/core/SyspathJavaLoader.java 2009-01-21 23:32:55 UTC (rev 5955) +++ trunk/jython/src/org/python/core/SyspathJavaLoader.java 2009-01-22 02:21:08 UTC (rev 5956) @@ -50,7 +50,7 @@ PyList path = sys.path; for (int i = 0; i < path.__len__(); i++) { - PyObject entry = path.__getitem__(i); + PyObject entry = replacePathItem(sys, i, path); if (entry instanceof SyspathArchive) { SyspathArchive archive = (SyspathArchive) entry; ZipEntry ze = archive.getEntry(entryRes); @@ -65,8 +65,7 @@ } String dir = sys.getPath(entry.__str__().toString()); try { - return new BufferedInputStream(new FileInputStream(new File( - dir, res))); + return new BufferedInputStream(new FileInputStream(new File(dir, res))); } catch (IOException e) { continue; } @@ -75,11 +74,28 @@ return null; } + static PyObject replacePathItem(PySystemState sys, int idx, PyList paths) { + PyObject path = paths.__getitem__(idx); + if (path instanceof SyspathArchive) { + // already an archive + return path; + } + + try { + // this has the side affect of adding the jar to the PackageManager during the + // initialization of the SyspathArchive + path = new SyspathArchive(sys.getPath(path.toString())); + } catch (Exception e) { + return path; + } + paths.__setitem__(idx, path); + return path; + } + // override from abstract base class - protected Class loadClass(String name, boolean resolve) + protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { - // First, if the Python runtime system has a default class loader, - // defer to it. + // First, if the Python runtime system has a default class loader, defer to it. PySystemState sys = Py.getSystemState(); ClassLoader classLoader = sys.getClassLoader(); if (classLoader != null) { @@ -97,44 +113,43 @@ return Class.forName(name, true, ClassLoader.getSystemClassLoader()); } catch(ClassNotFoundException e) {} - Class c = findLoadedClass(name); + Class<?> c = findLoadedClass(name); if(c != null) { return c; } PyList path = sys.path; for(int i = 0; i < path.__len__(); i++) { - InputStream fis = null; - File file = null; - int size = 0; - PyObject entry = path.__getitem__(i); + + InputStream fis; + int size; + PyObject entry = replacePathItem(sys, i, path); if(entry instanceof SyspathArchive) { SyspathArchive archive = (SyspathArchive)entry; String entryname = name.replace('.', SLASH_CHAR) + ".class"; ZipEntry ze = archive.getEntry(entryname); - if(ze != null) { - try { - fis = archive.getInputStream(ze); - size = (int)ze.getSize(); - } catch(IOException exc) { - ; - } + if(ze == null) { + continue; } + try { + fis = archive.getInputStream(ze); + size = (int)ze.getSize(); + } catch (IOException exc) { + continue; + } } else { String dir = entry.__str__().toString(); - file = getFile(dir, name); - if(file != null) { - size = (int)file.length(); - try { - fis = new FileInputStream(file); - } catch(FileNotFoundException e) { - ; - } + File file = getFile(dir, name); + if (file == null) { + continue; } + size = (int)file.length(); + try { + fis = new FileInputStream(file); + } catch (FileNotFoundException e) { + continue; + } } - if(fis == null) { - continue; - } try { byte[] buffer = new byte[size]; int nread = 0; @@ -143,14 +158,12 @@ } fis.close(); return loadClassFromBytes(name, buffer); - } catch(IOException e) { - continue; + } catch (IOException e) { + } finally { try { fis.close(); - } catch(IOException e) { - continue; - } + } catch (IOException e) {} } } @@ -173,9 +186,9 @@ return new RelativeFile(dir, accum + ".class"); } - private Class loadClassFromBytes(String name, byte[] data) { + private Class<?> loadClassFromBytes(String name, byte[] data) { // System.err.println("loadClassFromBytes("+name+", byte[])"); - Class c = defineClass(name, data, 0, data.length); + Class<?> c = defineClass(name, data, 0, data.length); resolveClass(c); Compiler.compileClass(c); return c; Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2009-01-21 23:32:55 UTC (rev 5955) +++ trunk/jython/src/org/python/core/imp.java 2009-01-22 02:21:08 UTC (rev 5956) @@ -318,41 +318,12 @@ return importer; } - static PyObject replacePathItem(PySystemState sys, PyObject path) { - if (path instanceof SyspathArchive) { - // already an archive - return null; - } - - try { - // this has the side affect of adding the jar to the PackageManager - // during the initialization of the SyspathArchive - return new SyspathArchive(sys.getPath(path.toString())); - } catch (Exception e) { - return null; - } - } - static PyObject find_module(String name, String moduleName, PyList path) { PyObject loader = Py.None; PySystemState sys = Py.getSystemState(); PyObject metaPath = sys.meta_path; - /* - * Needed to convert all entries on the path to SyspathArchives if - * necessary. - */ - PyList ppath = path == null ? sys.path : path; - for (int i = 0; i < ppath.__len__(); i++) { - PyObject p = ppath.__getitem__(i); - PyObject q = replacePathItem(sys, p); - if (q == null) { - continue; - } - ppath.__setitem__(i, q); - } - for (PyObject importer : metaPath.asIterable()) { PyObject findModule = importer.__getattr__("find_module"); loader = findModule.__call__(new PyObject[] { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-22 04:16:49
|
Revision: 5957 http://jython.svn.sourceforge.net/jython/?rev=5957&view=rev Author: fwierzbicki Date: 2009-01-22 04:16:47 +0000 (Thu, 22 Jan 2009) Log Message: ----------- Thanks to Marc Downie for this patch that fixes http://bugs.jython.org/issue1230 importing with '*' from java packages does not work with 2.5b1. Also added a test to test_java_integration.py. Modified Paths: -------------- trunk/jython/Lib/test/test_java_integration.py trunk/jython/src/org/python/core/packagecache/PackageManager.java trunk/jython/src/org/python/core/packagecache/PathPackageManager.java Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2009-01-22 02:21:08 UTC (rev 5956) +++ trunk/jython/Lib/test/test_java_integration.py 2009-01-22 04:16:47 UTC (rev 5957) @@ -20,6 +20,10 @@ from org.python.core.util import FileUtil from org.python.tests import BeanImplementation, Child, Listenable, CustomizableMapHolder +#Just for test_import_star +#java.util.regex was chosen for its small number of classes to reduce the pollution. +from java.util.regex import * + class InstantiationTest(unittest.TestCase): def test_cant_instantiate_abstract(self): self.assertRaises(TypeError, Component) @@ -378,6 +382,10 @@ self.assertEquals(7, m.initial) self.assertEquals(None, m.nonexistent, "Nonexistent fields should be passed on to the Map") + def test_import_star(self): + #Depends on "from java.util.regex import *" at the top. + x = Pattern.compile("foo") + self.assertEquals(x.flags(), 0) def test_main(): test_support.run_unittest(InstantiationTest, Modified: trunk/jython/src/org/python/core/packagecache/PackageManager.java =================================================================== --- trunk/jython/src/org/python/core/packagecache/PackageManager.java 2009-01-22 02:21:08 UTC (rev 5956) +++ trunk/jython/src/org/python/core/packagecache/PackageManager.java 2009-01-22 04:16:47 UTC (rev 5957) @@ -107,7 +107,7 @@ for (PyObject pyname : cls.keys().asIterable()) { if (!dict.has_key(pyname)) { String name = pyname.toString(); - jpkg.addClass(name, Py.findClass(name)); + jpkg.addClass(name, Py.findClass(jpkg.__name__ + "." + name)); } } Modified: trunk/jython/src/org/python/core/packagecache/PathPackageManager.java =================================================================== --- trunk/jython/src/org/python/core/packagecache/PathPackageManager.java 2009-01-22 02:21:08 UTC (rev 5956) +++ trunk/jython/src/org/python/core/packagecache/PathPackageManager.java 2009-01-22 04:16:47 UTC (rev 5957) @@ -164,7 +164,7 @@ if (pkgCand) { jpkg.addPackage(jname); } else { - jpkg.addClass(jname, Py.findClass(jname)); + jpkg.addClass(jname, Py.findClass(jpkg.__name__ + "." + jname)); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-22 19:50:23
|
Revision: 5959 http://jython.svn.sourceforge.net/jython/?rev=5959&view=rev Author: cgroves Date: 2009-01-22 19:50:18 +0000 (Thu, 22 Jan 2009) Log Message: ----------- Expose rich comparision methods on Java classes implementing Comparable Modified Paths: -------------- trunk/jython/Lib/test/test_java_integration.py trunk/jython/src/org/python/core/PyJavaType.java Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2009-01-22 04:38:25 UTC (rev 5958) +++ trunk/jython/Lib/test/test_java_integration.py 2009-01-22 19:50:18 UTC (rev 5959) @@ -7,9 +7,10 @@ from test import test_support -from java.lang import (ExceptionInInitializerError, String, Runnable, System, Runtime, Math, Byte) +from java.lang import (ClassCastException, ExceptionInInitializerError, String, Runnable, System, + Runtime, Math, Byte) from java.math import BigDecimal, BigInteger -from java.io import (FileInputStream, FileNotFoundException, FileOutputStream, FileWriter, +from java.io import (File, FileInputStream, FileNotFoundException, FileOutputStream, FileWriter, OutputStreamWriter, UnsupportedEncodingException) from java.util import ArrayList, Date, HashMap, Hashtable, StringTokenizer, Vector @@ -350,6 +351,39 @@ for i in v: pass + def test_comparable_delegation(self): + first_file = File("a") + first_date = Date(100) + for a, b, c in [(first_file, File("b"), File("c")), (first_date, Date(1000), Date())]: + self.assertTrue(a.compareTo(b) < 0) + self.assertEquals(-1, cmp(a, b)) + self.assertTrue(a.compareTo(c) < 0) + self.assertEquals(-1, cmp(a, c)) + self.assertEquals(0, a.compareTo(a)) + self.assertEquals(0, cmp(a, a)) + self.assertTrue(b.compareTo(a) > 0) + self.assertEquals(1, cmp(b, a)) + self.assertTrue(c.compareTo(b) > 0) + self.assertEquals(1, cmp(c, b)) + self.assertTrue(a < b) + self.assertTrue(a <= a) + self.assertTrue(b > a) + self.assertTrue(c >= a) + self.assertTrue(a != b) + l = [b, c, a] + self.assertEquals(a, min(l)) + self.assertEquals(c, max(l)) + l.sort() + self.assertEquals([a, b, c], l) + # Check that we fall back to the default comparison(class name) instead of using compareTo + # on non-Comparable types + self.assertRaises(ClassCastException, first_file.compareTo, first_date) + self.assertEquals(-1, cmp(first_file, first_date)) + self.assertTrue(first_file < first_date) + self.assertTrue(first_file <= first_date) + self.assertTrue(first_date > first_file) + self.assertTrue(first_date >= first_file) + class SecurityManagerTest(unittest.TestCase): def test_nonexistent_import_with_security(self): policy = test_support.findfile("python_home.policy") Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-01-22 04:38:25 UTC (rev 5958) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-01-22 19:50:18 UTC (rev 5959) @@ -402,6 +402,14 @@ return proxy.equals(oAsJava) ? Py.True : Py.False; } }); + addMethod(new PyBuiltinMethodNarrow("__ne__", 1) { + @Override + public PyObject __call__(PyObject o) { + Object proxy = self.getJavaProxy(); + Object oAsJava = o.__tojava__(proxy.getClass()); + return !proxy.equals(oAsJava) ? Py.True : Py.False; + } + }); addMethod(new PyBuiltinMethodNarrow("__hash__") { @Override public PyObject __call__() { @@ -415,6 +423,32 @@ } }); } + if(forClass == Comparable.class) { + addMethod(new ComparableMethod("__lt__", 1) { + @Override + protected boolean getResult(int comparison) { + return comparison < 0; + } + }); + addMethod(new ComparableMethod("__le__", 1) { + @Override + protected boolean getResult(int comparison) { + return comparison <= 0; + } + }); + addMethod(new ComparableMethod("__gt__", 1) { + @Override + protected boolean getResult(int comparison) { + return comparison > 0; + } + }); + addMethod(new ComparableMethod("__ge__", 1) { + @Override + protected boolean getResult(int comparison) { + return comparison >= 0; + } + }); + } } /** @@ -559,6 +593,25 @@ } } + private static abstract class ComparableMethod extends PyBuiltinMethodNarrow { + protected ComparableMethod(String name, int numArgs) { + super(name, numArgs); + } + @Override + public PyObject __call__(PyObject arg) { + Object asjava = arg.__tojava__(Object.class); + int compare; + try { + compare = ((Comparable<Object>)self.getJavaProxy()).compareTo(asjava); + } catch(ClassCastException classCast) { + return Py.NotImplemented; + } + return getResult(compare) ? Py.True : Py.False; + } + + protected abstract boolean getResult(int comparison); + } + private static Map<Class<?>, PyBuiltinMethod[]> getCollectionProxies() { if (collectionProxies == null) { collectionProxies = Generic.map(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-23 01:03:41
|
Revision: 5961 http://jython.svn.sourceforge.net/jython/?rev=5961&view=rev Author: fwierzbicki Date: 2009-01-23 01:03:39 +0000 (Fri, 23 Jan 2009) Log Message: ----------- Over-ride pyset in PyTuple so our tuples go back to being immutable. Fixes http://bugs.jython.org/issue1242. Modified Paths: -------------- trunk/jython/Lib/test/test_tuple.py trunk/jython/src/org/python/core/PyTuple.java Modified: trunk/jython/Lib/test/test_tuple.py =================================================================== --- trunk/jython/Lib/test/test_tuple.py 2009-01-22 20:20:59 UTC (rev 5960) +++ trunk/jython/Lib/test/test_tuple.py 2009-01-23 01:03:39 UTC (rev 5961) @@ -88,6 +88,12 @@ self.assertEqual(repr(a0), "()") self.assertEqual(repr(a2), "(0, 1, 2)") + def test_setitem(self): + #This test is equivalent to (1,2)[0] = 0 which was briefly broken in + #Jython 2.5b2 + import operator + self.assertRaises(TypeError, operator.setitem, (1,2), 0, 0) + def test_main(): test_support.run_unittest(TupleTest) Modified: trunk/jython/src/org/python/core/PyTuple.java =================================================================== --- trunk/jython/src/org/python/core/PyTuple.java 2009-01-22 20:20:59 UTC (rev 5960) +++ trunk/jython/src/org/python/core/PyTuple.java 2009-01-23 01:03:39 UTC (rev 5961) @@ -384,4 +384,9 @@ } return super.unsupportedopMessage(op, o2); } + + public void pyset(int index, PyObject value) { + throw Py.TypeError("'tuple' object does not support item assignment"); + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-25 12:18:55
|
Revision: 5974 http://jython.svn.sourceforge.net/jython/?rev=5974&view=rev Author: cgroves Date: 2009-01-25 12:15:25 +0000 (Sun, 25 Jan 2009) Log Message: ----------- Bring up to the current state of affairs Modified Paths: -------------- trunk/jython/registry trunk/jython/src/org/python/core/Options.java Modified: trunk/jython/registry =================================================================== --- trunk/jython/registry 2009-01-24 20:17:39 UTC (rev 5973) +++ trunk/jython/registry 2009-01-25 12:15:25 UTC (rev 5974) @@ -17,7 +17,7 @@ python.cachedir = cachedir # Setting this property to true disables the package scan for the cachedir. -# Please be aware that disabling this might break some java import statements +# Please be aware that disabling this will break imporing * from java packages #python.cachedir.skip = false # Properties to check for initializing and updating the package cache @@ -25,10 +25,6 @@ python.packages.paths = java.class.path, sun.boot.class.path python.packages.directories = java.ext.dirs -# To force JIT compilation of Jython code -- should be unnecessary -# Setting this to true will cause jdk1.2rc1 to core dump on Windows -python.options.compileClass = false - # Set verbosity to error, warning, message, comment, or debug # for varying levels of informative messages from Jython. Normally # this option is set from the command line. @@ -45,23 +41,12 @@ # Setting this to a valid codec name will cause the console to use a # different encoding when reading commands from the console. -# The default java encoding is still used when reading python sources -# from the filesystem. #python.console.encoding = cp850 # Setting this to false will allow Jython to provide access to # non-public fields, methods, and constructors of Java objects. python.security.respectJavaAccessibility = true -# List of choices for internal tables impl (PyJavaClasses canonical map etc.), -# these are separated through ':' and tryed from left to right. -# For long running applications under java2, needing classes unloading, -# in order to have jython runtime automatically discarding -# no longer needed info and avoding memory leakage, this can be set -# to weak or soft (=> an impl. using weak-refs or soft-refs will be used). -#python.options.internalTablesImpl = soft -#python.options.internalTablesImpl = weak - # Setting this to true will force Jython will use the first module # found on sys.path where java File.isFile() returns true. # Setting this to true has no effect on unix-type filesystems. @@ -90,15 +75,3 @@ # functionality by having an entry such as os:com.foo.jni.os #python.modules.builtin = whatever -# This specifies the command used by jythonc to compile Java source -# code, along with the complete classpath to use. -# python.jythonc.compiler = /depot/java/plat/bin/jikes -# python.jythonc.classpath = /usr/java1.2/jre/lib/rt.jar:/Jython/dist:. -# python.jythonc.compileropts = +E +D -g - -# python.os determines operating-specific features, similar to and overriding the -# Java property "os.name". -# Some generic values are also supported: 'nt', 'ce' and 'posix'. -# Uncomment the following line for the most generic OS behavior available. -#python.os=None - Modified: trunk/jython/src/org/python/core/Options.java =================================================================== --- trunk/jython/src/org/python/core/Options.java 2009-01-24 20:17:39 UTC (rev 5973) +++ trunk/jython/src/org/python/core/Options.java 2009-01-25 12:15:25 UTC (rev 5974) @@ -54,12 +54,6 @@ public static int verbose = Py.MESSAGE; /** - * Setting this to true will support old 1.0 style keyword+"_" names. This - * isn't needed any more due to improvements in the parser - */ - public static boolean deprecatedKeywordMangling = false; - - /** * A directory where the dynamically generated classes are written. Nothing is * ever read from here, it is only for debugging purposes. */ @@ -131,9 +125,6 @@ "options.showPythonProxyExceptions", Options.showPythonProxyExceptions); - Options.deprecatedKeywordMangling = getBooleanOption( - "deprecated.keywordMangling", Options.deprecatedKeywordMangling); - Options.respectJavaAccessibility = getBooleanOption( "security.respectJavaAccessibility", Options.respectJavaAccessibility); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-25 12:19:33
|
Revision: 5975 http://jython.svn.sourceforge.net/jython/?rev=5975&view=rev Author: cgroves Date: 2009-01-25 12:19:27 +0000 (Sun, 25 Jan 2009) Log Message: ----------- Use Python's mro to determine an mro for Java classes and interfaces. If the Java class has an mro conflict, resolve it by arbitrarily choosing an interface or class. If an interface or class involved in an mro conflict has had its dict modified, or has its dict modified, raise a TypeError. Modified Paths: -------------- trunk/jython/Lib/test/test_import_jy.py trunk/jython/Lib/test/test_java_integration.py trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyType.java Modified: trunk/jython/Lib/test/test_import_jy.py =================================================================== --- trunk/jython/Lib/test/test_import_jy.py 2009-01-25 12:15:25 UTC (rev 5974) +++ trunk/jython/Lib/test/test_import_jy.py 2009-01-25 12:19:27 UTC (rev 5975) @@ -8,6 +8,7 @@ import sys import tempfile import unittest +import subprocess from test import test_support from test_chdir import read, safe_mktemp, COMPILED_SUFFIX @@ -148,7 +149,11 @@ # causes a stack overflow if the bug occurs self.assertRaises(Exception, getattr, anygui, 'abc') + def test_import_star(self): + self.assertEquals(subprocess.call([sys.executable, + test_support.findfile("import_star_from_java.py")]), 0) + def test_main(): test_support.run_unittest(MislabeledImportTestCase, OverrideBuiltinsImportTestCase, Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2009-01-25 12:15:25 UTC (rev 5974) +++ trunk/jython/Lib/test/test_java_integration.py 2009-01-25 12:19:27 UTC (rev 5975) @@ -20,6 +20,7 @@ from org.python.core.util import FileUtil from org.python.tests import BeanImplementation, Child, Listenable, CustomizableMapHolder +from org.python.tests.mro import (ConfusedOnGetitemAdd, FirstPredefinedGetitem, GetitemAdder) class InstantiationTest(unittest.TestCase): def test_cant_instantiate_abstract(self): @@ -411,11 +412,19 @@ self.assertEquals(7, m.held["initial"], "Existing fields should still be accessible") self.assertEquals(7, m.initial) self.assertEquals(None, m.nonexistent, "Nonexistent fields should be passed on to the Map") + + def test_adding_on_interface(self): + GetitemAdder.addPredefined() + class UsesInterfaceMethod(FirstPredefinedGetitem): + pass + self.assertEquals("key", UsesInterfaceMethod()["key"]) + + def test_add_on_mro_conflict(self): + """Adding same-named methods to Java classes with MRO conflicts produces TypeError""" + GetitemAdder.addPredefined() + self.assertRaises(TypeError, __import__, "org.python.tests.mro.ConfusedOnImport") + self.assertRaises(TypeError, GetitemAdder.addPostdefined) - def test_import_star(self): - self.assertEquals(subprocess.call([sys.executable, - test_support.findfile("import_star_from_java.py")]), 0) - def test_main(): test_support.run_unittest(InstantiationTest, BeanTest, Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-01-25 12:15:25 UTC (rev 5974) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-01-25 12:19:27 UTC (rev 5975) @@ -35,6 +35,19 @@ private static Map<Class<?>, PyBuiltinMethod[]> collectionProxies; + /** + * Other Java classes this type has MRO conflicts with. This doesn't matter for Java method + * resolution, but if Python methods are added to the type, the added methods can't overlap with + * methods added to any of the types in this set. If this type doesn't have any known conflicts, + * this is null. + */ + private Set<PyJavaType> conflicted; + + /** + * The names of methods that have been added to this class. + */ + private Set<String> modified; + public static PyObject wrapJavaObject(Object o) { PyObject obj = new PyObjectDerived(PyType.fromClass(o.getClass())); obj.javaProxy = o; @@ -62,11 +75,101 @@ return !(attr instanceof PyReflectedField || attr instanceof PyReflectedFunction); } - PyObject[] compute_mro() { - return mro; + @Override + public void addMethod(PyBuiltinMethod meth) { + if (modified == null) { + modified = Generic.set(); + } + if (modified.add(meth.info.getName())) { + if (conflicted != null) { + for (PyJavaType conflict : conflicted) { + if (conflict.modified != null + && conflict.modified.contains(meth.info.getName())) { + throw Py.TypeError(getName() + + " does not have a consistent method resolution" + " order with " + + conflict.getName() + ", and it already has " + + meth.info.getName() + " added for Python"); + } + } + } + } + super.addMethod(meth); } @Override + public void removeMethod(PyBuiltinMethod meth) { + super.removeMethod(meth); + if (modified != null) { + modified.remove(meth.info.getName()); + } + } + + @Override + void handleMroError(MROMergeState[] toMerge, List<PyObject> mro) { + if (underlying_class != null) { + // If this descends from PyObject, don't do the Java mro cleanup + super.handleMroError(toMerge, mro); + } + Set<PyJavaType> inConflict = Generic.set(); + PyJavaType winner = null; + for (MROMergeState mergee : toMerge) { + for (int i = mergee.next; i < mergee.mro.length; i++) { + if (mergee.mro[i] == PyObject.TYPE + || mergee.mro[i] == PyType.fromClass(Object.class)) { + continue; + } + if (winner == null) { + // Pick an arbitrary class to be added to the mro next and break the conflict. + // If method name conflicts were allowed between methods added to Java types, + // it would go first, but that's prevented, so being a winner doesn't actually + // get it anything + winner = (PyJavaType)mergee.mro[i]; + } + inConflict.add((PyJavaType)mergee.mro[i]); + } + } + + Set<String> allModified = Generic.set(); + PyJavaType[] conflicted = inConflict.toArray(new PyJavaType[inConflict.size()]); + for (PyJavaType type : conflicted) { + if (type.modified == null) { + continue; + } + for (String method : type.modified) { + if (!allModified.add(method)) { // Another type in conflict has this method, fail + PyList types = new PyList(); + for (PyJavaType othertype : conflicted) { + if (othertype.modified != null && othertype.modified.contains(method)) { + types.add(othertype); + } + } + throw Py.TypeError(String.format("Supertypes that share a method " + + " have an MRO conflict[method=%s, types=%s]", method, types)); + } + } + } + + // We can keep trucking, there aren't any existing method name conflicts. Mark the + // conflicts in all the classes so further method additions can check for trouble + for (PyJavaType type : conflicted) { + for (PyJavaType otherType : inConflict) { + if (otherType != type) { + if (type.conflicted == null) { + type.conflicted = Generic.set(); + } + type.conflicted.add(otherType); + } + } + } + + // Add our winner to the mro, clear the clog, and try to finish the rest + mro.add(winner); + for (MROMergeState mergee : toMerge) { + mergee.removeFromUnmerged(winner); + } + computeMro(toMerge, mro); + } + @Override protected void init(Class<?> forClass) { name = forClass.getName(); // Strip the java fully qualified class name from Py classes in core @@ -83,31 +186,30 @@ } else { javaProxy = forClass; objtype = PyType.fromClass(Class.class); - // Wrapped Java types fill in their mro first using their base class and then all of - // their interfaces. - if (baseClass == null) { + // Wrapped Java types fill in their mro first using all of their interfaces then their + // super class. + List<PyObject> visibleBases = Generic.list(); + for (Class<?> iface : forClass.getInterfaces()) { + if (iface == PyProxy.class || iface == ClassDictInit.class) { + // Don't show the interfaces added by proxy type construction; otherwise Python + // subclasses of proxy types and another Java interface can't make a consistent + // mro + continue; + } + visibleBases.add(PyType.fromClass(iface)); + } + if (javaProxy == Object.class) { base = PyType.fromClass(PyObject.class); - } else if (javaProxy == Class.class) { + } else if(baseClass == null) { + base = PyType.fromClass(Object.class); + }else if (javaProxy == Class.class) { base = PyType.fromClass(PyType.class); } else { base = PyType.fromClass(baseClass); } - bases = new PyObject[1 + forClass.getInterfaces().length]; - bases[0] = base; - for (int i = 1; i < bases.length; i++) { - bases[i] = PyType.fromClass(forClass.getInterfaces()[i - 1]); - } - Set<PyObject> seen = Generic.set(); - List<PyObject> mros = Generic.list(); - mros.add(this); - for (PyObject obj : bases) { - for (PyObject mroObj : ((PyType)obj).mro) { - if (seen.add(mroObj)) { - mros.add(mroObj); - } - } - } - mro = mros.toArray(new PyObject[mros.size()]); + visibleBases.add(base); + this.bases = visibleBases.toArray(new PyObject[visibleBases.size()]); + mro = computeMro(); } // PyReflected* can't call or access anything from non-public classes that aren't in @@ -392,7 +494,8 @@ || getDescrMethod(forClass, "_doset", OO) != null; has_delete = getDescrMethod(forClass, "__delete__", PyObject.class) != null || getDescrMethod(forClass, "_dodel", PyObject.class) != null; - } else { + } + if (forClass == Object.class) { // Pass __eq__ and __repr__ through to subclasses of Object addMethod(new PyBuiltinMethodNarrow("__eq__", 1) { @Override @@ -468,42 +571,39 @@ */ private void handleSuperMethodArgCollisions(Class<?> forClass) { for (Class<?> iface : forClass.getInterfaces()) { - for (Method meth : iface.getMethods()) { - if (!Modifier.isPublic(meth.getDeclaringClass().getModifiers())) { - // Ignore methods from non-public interfaces as they're similarly bugged - continue; + mergeMethods(iface); + } + if (forClass.getSuperclass() != null) { + mergeMethods(forClass.getSuperclass()); + } + } + + private void mergeMethods(Class<?> parent) { + for (Method meth : parent.getMethods()) { + if (!Modifier.isPublic(meth.getDeclaringClass().getModifiers())) { + // Ignore methods from non-public interfaces as they're similarly bugged + continue; + } + String nmethname = normalize(meth.getName()); + PyObject[] where = new PyObject[1]; + PyObject obj = lookup_where(nmethname, where); + if (obj == null) { + // Nothing in our supertype hierarchy defines something with this name, so it + // must not be visible there. + continue; + } else if (where[0] == this) { + // This method is the only thing defining items in this class' dict, so it must + // be a PyReflectedFunction created here. See if it needs the current method + // added to it. + if (!((PyReflectedFunction)obj).handles(meth)) { + ((PyReflectedFunction)obj).addMethod(meth); } - String nmethname = normalize(meth.getName()); - PyObject[] where = new PyObject[1]; - PyObject obj = lookup_where(nmethname, where); - if (obj == null) { - // Nothing in our supertype hierarchy defines something with this name, so it - // must not be visible there. - continue; - } else if (where[0] == this) { - // This method is the only thing defining items in this class' dict, so it must - // be a PyReflectedFunction created here. See if it needs the current method - // added to it. - if (!((PyReflectedFunction)obj).handles(meth)) { - ((PyReflectedFunction)obj).addMethod(meth); - } - } else { - // There's something in a superclass with the same name. If this class extends a - // class and doesn't just implement something, the extended class is first in - // mro, so items defined on the extended class will show up here. Thanks to that - // and copying the base function, we can get away with just looping over - // interface methods. - PyReflectedFunction func; - if (obj instanceof PyReflectedFunction) { - func = ((PyReflectedFunction)obj).copy(); - if (!func.handles(meth)) { - func.addMethod(meth); - } - } else { - func = new PyReflectedFunction(meth); - } - dict.__setitem__(nmethname, func); - } + } else { + // There's something in a superclass with the same name. Add an item to this type's + // dict to hide it. If it's this method, nothing's changed. If it's a field, we + // want to make the method visible. If it's a different method, it'll be added to + // the reflected function created here in a later call. + dict.__setitem__(nmethname, new PyReflectedFunction(meth)); } } } Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-01-25 12:15:25 UTC (rev 5974) +++ trunk/jython/src/org/python/core/PyType.java 2009-01-25 12:19:27 UTC (rev 5975) @@ -507,7 +507,7 @@ private void mro_internal() { if (getType() == TYPE) { - mro = compute_mro(); + mro = computeMro(); } else { PyObject mroDescr = getType().lookup("mro"); if (mroDescr == null) { @@ -652,55 +652,18 @@ return acc.toArray(new PyObject[acc.size()]); } - private static boolean tail_contains(PyObject[] lst, int whence, PyObject o) { - int n = lst.length; - for (int i = whence + 1; i < n; i++) { - if (lst[i] == o) { - return true; - } - } - return false; - } - - private static PyException mro_error(PyObject[][] to_merge, int[] remain) { - StringBuilder msg = new StringBuilder("Cannot create a consistent method resolution\n" - + "order (MRO) for bases "); - PyDictionary set = new PyDictionary(); - for (int i = 0; i < to_merge.length; i++) { - PyObject[] lst = to_merge[i]; - if (remain[i] < lst.length) { - set.__setitem__(lst[remain[i]], Py.None); - } - } - PyObject iter = set.__iter__(); - PyObject cur; - boolean subq = false; - while ((cur = iter.__iternext__()) != null) { - PyObject name = cur.__findattr__("__name__"); - if (!subq) { - subq = true; - } else { - msg.append(", "); - } - msg.append(name == null ? "?" : name.toString()); - } - return Py.TypeError(msg.toString()); - } - @ExposedMethod(defaults = "null", doc = BuiltinDocs.type_mro_doc) final PyList type_mro(PyObject o) { if (o == null) { - return new PyList(compute_mro()); + return new PyList(computeMro()); } - return new PyList(((PyType)o).compute_mro()); + return new PyList(((PyType)o).computeMro()); } - PyObject[] compute_mro() { - PyObject[] bases = this.bases; - int n = bases.length; - for (int i = 0; i < n; i++) { + PyObject[] computeMro() { + for (int i = 0; i < bases.length; i++) { PyObject cur = bases[i]; - for (int j = i + 1; j < n; j++) { + for (int j = i + 1; j < bases.length; j++) { if (bases[j] == cur) { PyObject name = cur.__findattr__("__name__"); throw Py.TypeError("duplicate base class " + @@ -709,58 +672,77 @@ } } - int nmerge = n + 1; - PyObject[][] to_merge = new PyObject[nmerge][]; - int[] remain = new int[nmerge]; - - for (int i = 0; i < n; i++) { - PyObject cur = bases[i]; - remain[i] = 0; - if (cur instanceof PyType) { - to_merge[i] = ((PyType)cur).mro; - } else if (cur instanceof PyClass) { - to_merge[i] = classic_mro((PyClass)cur); + MROMergeState[] toMerge = new MROMergeState[bases.length + 1]; + for (int i = 0; i < bases.length; i++) { + toMerge[i] = new MROMergeState(); + if (bases[i] instanceof PyType) { + toMerge[i].mro = ((PyType)bases[i]).mro; + } else if (bases[i] instanceof PyClass) { + toMerge[i].mro = classic_mro((PyClass)bases[i]); } } + toMerge[bases.length] = new MROMergeState(); + toMerge[bases.length].mro = bases; - to_merge[n] = bases; - remain[n] = 0; + List<PyObject> mro = Generic.list(); + mro.add(this); + return computeMro(toMerge, mro); + } - List<PyObject> acc = Generic.list(); - acc.add(this); - - int empty_cnt = 0; - - scan : for (int i = 0; i < nmerge; i++) { - PyObject candidate; - PyObject[] cur = to_merge[i]; - if (remain[i] >= cur.length) { - empty_cnt++; + PyObject[] computeMro(MROMergeState[] toMerge, List<PyObject> mro) { + scan : for (int i = 0; i < toMerge.length; i++) { + if (toMerge[i].isMerged()) { continue scan; } - candidate = cur[remain[i]]; - for (int j = 0; j < nmerge; j++) - if (tail_contains(to_merge[j], remain[j], candidate)) { + PyObject candidate = toMerge[i].getCandidate(); + for (MROMergeState mergee : toMerge) { + if(mergee.unmergedContains(candidate)) { continue scan; } - acc.add(candidate); - for (int j = 0; j < nmerge; j++) { - if (remain[j] < to_merge[j].length && to_merge[j][remain[j]] == candidate) { - remain[j]++; - } } - // restart scan - i = -1; - empty_cnt = 0; + mro.add(candidate); + for (MROMergeState element : toMerge) { + element.noteMerged(candidate); + } + i = -1;// restart scan } - if (empty_cnt == nmerge) { - return acc.toArray(bases); + for (MROMergeState mergee : toMerge) { + if (!mergee.isMerged()) { + handleMroError(toMerge, mro); + } } - throw mro_error(to_merge, remain); + return mro.toArray(new PyObject[mro.size()]); } + /** + * Must either throw an exception, or bring the merges in <code>toMerge</code> to completion by + * finishing filling in <code>mro</code>. + */ + void handleMroError(MROMergeState[] toMerge, List<PyObject> mro) { + StringBuilder msg = new StringBuilder("Cannot create a consistent method resolution\n" + + "order (MRO) for bases "); + Set<PyObject> set = Generic.set(); + for (MROMergeState mergee : toMerge) { + if(!mergee.isMerged()) { + set.add(mergee.mro[0]); + } + } + boolean first = true; + for (PyObject unmerged : set) { + PyObject name = unmerged.__findattr__("__name__"); + if (first) { + first = false; + } else { + msg.append(", "); + } + msg.append(name == null ? "?" : name.toString() + new PyList(((PyType)unmerged).bases)); + } + throw Py.TypeError(msg.toString()); + } + + /** * Finds the parent of type with an underlying_class or with slots sans a __dict__ * slot. */ @@ -1076,6 +1058,13 @@ dict.__setitem__(pmd.getName(), pmd); } + /** + * Removes the given method from this type's dict or raises a KeyError. + */ + public void removeMethod(PyBuiltinMethod meth) { + dict.__delitem__(meth.info.getName()); + } + protected void checkSetattr() { if (builtin) { throw Py.TypeError(String.format("can't set attributes of built-in/extension type " @@ -1380,4 +1369,64 @@ return pytyp; } } + + /** + * Tracks the status of merging a single base into a subclass' mro in computeMro. + */ + static class MROMergeState { + + /** The mro of the base type we're representing. */ + public PyObject[] mro; + + /** + * The index of the next item to be merged from mro, or mro.length if this base has been + * completely merged. + */ + public int next; + + public boolean isMerged() { + return mro.length == next; + } + + public PyObject getCandidate() { + return mro[next]; + } + + /** + * Marks candidate as merged for this base if it's the next item to be merged. + */ + public void noteMerged(PyObject candidate) { + if (!isMerged() && getCandidate() == candidate) { + next++; + } + } + + /** + * Returns true if candidate is in the items past this state's next item to be merged. + */ + public boolean unmergedContains(PyObject candidate) { + for (int i = next + 1; i < mro.length; i++) { + if (mro[i] == candidate) { + return true; + } + } + return false; + } + + /** + * Removes the given item from this state's mro if it isn't already finished. + */ + public void removeFromUnmerged(PyJavaType winner) { + if (isMerged()) { + return; + } + List<PyObject> newMro = Generic.list(); + for (PyObject mroEntry : mro) { + if (mroEntry != winner) { + newMro.add(mroEntry); + } + } + mro = newMro.toArray(new PyObject[newMro.size()]); + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-26 00:33:27
|
Revision: 5979 http://jython.svn.sourceforge.net/jython/?rev=5979&view=rev Author: cgroves Date: 2009-01-26 00:33:21 +0000 (Mon, 26 Jan 2009) Log Message: ----------- Include Python Java subclasses as bases as well as the Java proxy type, as it may have additional methods in its Python. Return the proxyClass directly from getProxyType as we're setting that on Python subclasses now. Modified Paths: -------------- trunk/jython/Lib/test/test_java_subclasses.py trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyType.java trunk/jython/tests/java/org/python/tests/Coercions.java Modified: trunk/jython/Lib/test/test_java_subclasses.py =================================================================== --- trunk/jython/Lib/test/test_java_subclasses.py 2009-01-25 21:06:04 UTC (rev 5978) +++ trunk/jython/Lib/test/test_java_subclasses.py 2009-01-26 00:33:21 UTC (rev 5979) @@ -12,7 +12,7 @@ from java.awt import Color, Component, Dimension, Rectangle from javax.swing.table import AbstractTableModel -from org.python.tests import BeanInterface, Callbacker +from org.python.tests import BeanInterface, Callbacker, Coercions class InterfaceTest(unittest.TestCase): def test_java_calling_python_interface_implementation(self): @@ -117,16 +117,27 @@ pass def test_multilevel_override(self): - class SubDate(Date): - def toString(self): - s = Date.toString(self) - return 'SubDate -> Date' + runs = [] + class SubDate(Date): + def run(self): + runs.append("SubDate") - class SubSubDate(SubDate): + def method(self): + return "SubDateMethod" + + def toString(self): + s = Date.toString(self) + return 'SubDate -> Date' + + class SubSubDate(SubDate, Runnable): def toString(self): return 'SubSubDate -> ' + SubDate.toString(self) + self.assertEquals("SubDate -> Date", SubDate().toString()) self.assertEquals("SubSubDate -> SubDate -> Date", SubSubDate().toString()) + self.assertEquals("SubDateMethod", SubSubDate().method()) + Coercions.runRunnable(SubSubDate()) + self.assertEquals(["SubDate"], runs) def test_passthrough(self): class CallbackPassthrough(Callbacker.Callback): Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-01-25 21:06:04 UTC (rev 5978) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-01-26 00:33:21 UTC (rev 5979) @@ -58,11 +58,6 @@ super(TYPE == null ? fromClass(PyType.class) : TYPE); } - @Override - public Class<?> getProxyType() { - return (Class<?>)javaProxy; - } - // Java types are ok with things being added and removed from their dicts as long as there isn't // something there, so let these checks through @Override Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-01-25 21:06:04 UTC (rev 5978) +++ trunk/jython/src/org/python/core/PyType.java 2009-01-26 00:33:21 UTC (rev 5979) @@ -191,13 +191,24 @@ List<PyObject> cleanedBases = Generic.list(); boolean addedProxyType = false; for (PyObject base : bases_list) { - if (base instanceof PyJavaType) { - if (!addedProxyType) { + if (!(base instanceof PyType)) { + cleanedBases.add(base); + continue; + } + Class<?> proxy = ((PyType)base).getProxyType(); + if (proxy == null) { + cleanedBases.add(base);// non-proxy types go straight into our lookup + } 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; } - } else { - cleanedBases.add(base); } } bases_list = cleanedBases.toArray(new PyObject[cleanedBases.size()]); @@ -593,15 +604,7 @@ * Returns the Java Class that this type inherits from, or null if this type is Python-only. */ public Class<?> getProxyType() { - for (PyObject base : bases) { - if (base instanceof PyType) { - Class<?> javaType = ((PyType)base).getProxyType(); - if (javaType != null) { - return javaType; - } - } - } - return null; + return (Class<?>)javaProxy; } private synchronized void attachSubclass(PyType subtype) { @@ -1206,6 +1209,10 @@ throw Py.TypeError(String.format("can't delete %s.__name__", name)); } + /** + * Returns the actual dict underlying this type instance. Changes to Java types should go + * through {@link #addMethod} and {@link #removeMethod}, or unexpected mro errors can occur. + */ public PyObject fastGetDict() { return dict; } Modified: trunk/jython/tests/java/org/python/tests/Coercions.java =================================================================== --- trunk/jython/tests/java/org/python/tests/Coercions.java 2009-01-25 21:06:04 UTC (rev 5978) +++ trunk/jython/tests/java/org/python/tests/Coercions.java 2009-01-26 00:33:21 UTC (rev 5979) @@ -100,4 +100,8 @@ } return true; } + + public static void runRunnable(Runnable r){ + r.run(); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-26 02:21:09
|
Revision: 5981 http://jython.svn.sourceforge.net/jython/?rev=5981&view=rev Author: cgroves Date: 2009-01-26 02:21:05 +0000 (Mon, 26 Jan 2009) Log Message: ----------- Defer resolving inner classes till the containing class is fully resolved. Fixes issue #1234. Modified Paths: -------------- trunk/jython/Lib/test/test_import_jy.py trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyType.java Added Paths: ----------- trunk/jython/tests/java/org/python/tests/inbred/ trunk/jython/tests/java/org/python/tests/inbred/Metis.java trunk/jython/tests/java/org/python/tests/inbred/Zeus.java Modified: trunk/jython/Lib/test/test_import_jy.py =================================================================== --- trunk/jython/Lib/test/test_import_jy.py 2009-01-26 01:19:12 UTC (rev 5980) +++ trunk/jython/Lib/test/test_import_jy.py 2009-01-26 02:21:05 UTC (rev 5981) @@ -153,6 +153,11 @@ self.assertEquals(subprocess.call([sys.executable, test_support.findfile("import_star_from_java.py")]), 0) + def test_selfreferential_classes(self): + from org.python.tests.inbred import Metis + from org.python.tests.inbred import Zeus + self.assertEquals(Metis, Zeus.Athena.__bases__[0]) + self.assertEquals(Zeus, Metis.__bases__[0]) def test_main(): test_support.run_unittest(MislabeledImportTestCase, Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-01-26 01:19:12 UTC (rev 5980) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-01-26 02:21:05 UTC (rev 5981) @@ -15,8 +15,6 @@ import java.util.Set; import org.python.core.util.StringUtil; -import org.python.expose.ExposeAsSuperclass; -import org.python.expose.ExposedType; import org.python.util.Generic; public class PyJavaType extends PyType { @@ -164,8 +162,9 @@ } computeMro(toMerge, mro); } + @Override - protected void init(Class<?> forClass) { + protected void init(Class<?> forClass, Set<PyJavaType> needsInners) { name = forClass.getName(); // Strip the java fully qualified class name from Py classes in core if (name.startsWith("org.python.core.Py")) { @@ -179,8 +178,9 @@ underlying_class = forClass; computeLinearMro(baseClass); } else { + needsInners.add(this); javaProxy = forClass; - objtype = PyType.fromClass(Class.class); + objtype = PyType.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(); @@ -191,16 +191,16 @@ // mro continue; } - visibleBases.add(PyType.fromClass(iface)); + visibleBases.add(PyType.fromClassSkippingInners(iface, needsInners)); } if (javaProxy == Object.class) { - base = PyType.fromClass(PyObject.class); + base = PyType.fromClassSkippingInners(PyObject.class, needsInners); } else if(baseClass == null) { - base = PyType.fromClass(Object.class); + base = PyType.fromClassSkippingInners(Object.class, needsInners); }else if (javaProxy == Class.class) { - base = PyType.fromClass(PyType.class); + base = PyType.fromClassSkippingInners(PyType.class, needsInners); } else { - base = PyType.fromClass(baseClass); + base = PyType.fromClassSkippingInners(baseClass, needsInners); } visibleBases.add(base); this.bases = visibleBases.toArray(new PyObject[visibleBases.size()]); @@ -449,21 +449,6 @@ } else { dict.__setitem__("__init__", reflctr); } - 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 && - 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); - } - dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner)); - } - } for (Map.Entry<Class<?>, PyBuiltinMethod[]> entry : getCollectionProxies().entrySet()) { if (entry.getKey() == forClass) { for (PyBuiltinMethod meth : entry.getValue()) { Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-01-26 01:19:12 UTC (rev 5980) +++ trunk/jython/src/org/python/core/PyType.java 2009-01-26 02:21:05 UTC (rev 5981) @@ -357,7 +357,7 @@ * 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) { + protected void init(Class<?> forClass, Set<PyJavaType> needsInners) { underlying_class = forClass; if (underlying_class == PyObject.class) { mro = new PyType[] {this}; @@ -939,24 +939,24 @@ } // 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()); + fromClass(builder.getTypeClass()).init(builder.getTypeClass(), null); } } - private static PyType addFromClass(Class<?> c) { + 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); + return createType(c, needsInners); } private static TypeBuilder getBuilder(Class<?> c) { return classToBuilder == null ? null : classToBuilder.get(c); } - private static PyType createType(Class<?> c) { + private static PyType createType(Class<?> c, Set<PyJavaType> needsInners) { PyType newtype; if (c == PyType.class) { newtype = new PyType(false); @@ -975,22 +975,56 @@ class_to_type.put(c, newtype); newtype.builtin = true; - newtype.init(c); + 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); + addFromClass(PyType.class, null); } PyType type = class_to_type.get(c); if (type != null) { return type; } - return addFromClass(c); + // 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; } + 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); Added: trunk/jython/tests/java/org/python/tests/inbred/Metis.java =================================================================== --- trunk/jython/tests/java/org/python/tests/inbred/Metis.java (rev 0) +++ trunk/jython/tests/java/org/python/tests/inbred/Metis.java 2009-01-26 02:21:05 UTC (rev 5981) @@ -0,0 +1,3 @@ +package org.python.tests.inbred; + +public interface Metis extends Zeus {} Added: trunk/jython/tests/java/org/python/tests/inbred/Zeus.java =================================================================== --- trunk/jython/tests/java/org/python/tests/inbred/Zeus.java (rev 0) +++ trunk/jython/tests/java/org/python/tests/inbred/Zeus.java 2009-01-26 02:21:05 UTC (rev 5981) @@ -0,0 +1,11 @@ +package org.python.tests.inbred; + +/** + * Zeus ate Metis to prevent her from giving birth, but Athena was born inside Zeus' head anyway. By + * the mythology Metis should extend from Oceanus and Tethys, but we need Metis to extend Zeus to + * get the kind of inheritance that caused http://bugs.jython.org/issue1234 + */ +public interface Zeus { + + public interface Athena extends Metis {} +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-26 03:10:39
|
Revision: 5982 http://jython.svn.sourceforge.net/jython/?rev=5982&view=rev Author: cgroves Date: 2009-01-26 03:10:36 +0000 (Mon, 26 Jan 2009) Log Message: ----------- Try to assign to a static field for a given name in __setattr__ on a Java type before filling something in on the dict. Fixes bug #1241 Modified Paths: -------------- trunk/jython/Lib/test/test_java_visibility.py trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/PyType.java trunk/jython/tests/java/org/python/tests/Visible.java Modified: trunk/jython/Lib/test/test_java_visibility.py =================================================================== --- trunk/jython/Lib/test/test_java_visibility.py 2009-01-26 02:21:05 UTC (rev 5981) +++ trunk/jython/Lib/test/test_java_visibility.py 2009-01-26 03:10:36 UTC (rev 5982) @@ -68,6 +68,11 @@ v = Visible() self.assertEquals(Results.PUBLIC_FIELD, v.visibleField) self.assertEquals(Results.PUBLIC_STATIC_FIELD, Visible.visibleStaticField) + Visible.visibleStaticField = Results.PUBLIC_STATIC_FIELD + 1 + self.assertEquals(Results.PUBLIC_STATIC_FIELD + 1, Visible.visibleStaticField) + self.assertEquals(Results.PUBLIC_STATIC_FIELD + 1, Visible.getVisibleStaticField()) + Visible.setVisibleStaticField(Results.PUBLIC_STATIC_FIELD) + self.assertEquals(Results.PUBLIC_STATIC_FIELD, Visible.visibleStaticField) self.assertEquals(Results.PUBLIC_METHOD, v.visibleInstance(0)) self.assertEquals(Results.OVERLOADED_PUBLIC_METHOD, v.visibleInstance('a')) self.assertEquals(Results.EXTRA_ARG_PUBLIC_METHOD, v.visibleInstance(0, 'b')) Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-01-26 02:21:05 UTC (rev 5981) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-01-26 03:10:36 UTC (rev 5982) @@ -56,45 +56,51 @@ super(TYPE == null ? fromClass(PyType.class) : TYPE); } - // Java types are ok with things being added and removed from their dicts as long as there isn't - // something there, so let these checks through - @Override - protected void checkDelattr() {} - - @Override - protected void checkSetattr() {} - protected boolean useMetatypeFirst(PyObject attr) { return !(attr instanceof PyReflectedField || attr instanceof PyReflectedFunction); } + // Java types are ok with things being added and removed from their dicts as long as there isn't @Override - public void addMethod(PyBuiltinMethod meth) { + void type___setattr__(String name, PyObject value) { + PyObject field = lookup(name);// If we have a static field that takes this, go with that + if (field != null) { + if (field._doset(null, value)) { + return; + } + } if (modified == null) { modified = Generic.set(); } - if (modified.add(meth.info.getName())) { + if (modified.add(name)) { if (conflicted != null) { for (PyJavaType conflict : conflicted) { - if (conflict.modified != null - && conflict.modified.contains(meth.info.getName())) { + if (conflict.modified != null && conflict.modified.contains(name)) { throw Py.TypeError(getName() - + " does not have a consistent method resolution" + " order with " - + conflict.getName() + ", and it already has " - + meth.info.getName() + " added for Python"); + + " does not have a consistent method resolution order with " + + conflict.getName() + ", and it already has " + name + + " added for Python"); } } } } - super.addMethod(meth); + object___setattr__(name, value); + postSetattr(name); } @Override - public void removeMethod(PyBuiltinMethod meth) { - super.removeMethod(meth); + void type___delattr__(String name) { + PyObject field = lookup(name); + if (field == null) { + throw Py.NameError("attribute not found: "+name); + } + if (!field.jdontdel()) { + object___delattr__(name); + } if (modified != null) { - modified.remove(meth.info.getName()); + modified.remove(name); } + postDelattr(name); } @Override @@ -136,8 +142,8 @@ types.add(othertype); } } - throw Py.TypeError(String.format("Supertypes that share a method " - + " have an MRO conflict[method=%s, types=%s]", method, types)); + throw Py.TypeError(String.format("Supertypes that share a modified attribute " + + " have an MRO conflict[attribute=%s, types=%s]", method, types)); } } } Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2009-01-26 02:21:05 UTC (rev 5981) +++ trunk/jython/src/org/python/core/PyObject.java 2009-01-26 03:10:36 UTC (rev 5982) @@ -1033,10 +1033,6 @@ return false; } - boolean jtryset(PyObject container, PyObject value) { - return _doset(container, value); - } - boolean jdontdel() { return false; } @@ -3682,7 +3678,7 @@ object___setattr__(asName(name), value); } - private final void object___setattr__(String name, PyObject value) { + final void object___setattr__(String name, PyObject value) { PyObject descr = objtype.lookup(name); boolean set = false; Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2009-01-26 02:21:05 UTC (rev 5981) +++ trunk/jython/src/org/python/core/PySystemState.java 2009-01-26 03:10:36 UTC (rev 5982) @@ -327,7 +327,7 @@ setWarnoptions(value); } else { PyObject ret = getType().lookup(name); // xxx fix fix fix - if (ret != null && ret.jtryset(this, value)) { + if (ret != null && ret._doset(this, value)) { return; } __dict__.__setitem__(name, value); @@ -338,7 +338,7 @@ checkMustExist(name); PyObject ret = getType().lookup(name); // xxx fix fix fix if (ret != null) { - ret.jtryset(this, PyAttributeDeleted.INSTANCE); + ret._doset(this, PyAttributeDeleted.INSTANCE); } try { __dict__.__delitem__(name); Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-01-26 02:21:05 UTC (rev 5981) +++ trunk/jython/src/org/python/core/PyType.java 2009-01-26 03:10:36 UTC (rev 5982) @@ -1092,26 +1092,26 @@ */ public void addMethod(PyBuiltinMethod meth) { PyMethodDescr pmd = meth.makeDescriptor(this); - dict.__setitem__(pmd.getName(), pmd); + __setattr__(pmd.getName(), pmd); } /** * Removes the given method from this type's dict or raises a KeyError. */ public void removeMethod(PyBuiltinMethod meth) { - dict.__delitem__(meth.info.getName()); + __delattr__(meth.info.getName()); } - protected void checkSetattr() { + void type___setattr__(String name, PyObject value) { if (builtin) { throw Py.TypeError(String.format("can't set attributes of built-in/extension type " + "'%s'", this.name)); } + super.__setattr__(name, value); + postSetattr(name); } - final void type___setattr__(String name, PyObject value) { - checkSetattr(); - super.__setattr__(name, value); + void postSetattr(String name) { if (name == "__set__") { if (!has_set && lookup("__set__") != null) { traverse_hierarchy(false, new OnType() { @@ -1145,15 +1145,19 @@ } protected void checkDelattr() { + } + + void type___delattr__(String name) { if (builtin) { throw Py.TypeError(String.format("can't set attributes of built-in/extension type " + "'%s'", this.name)); } + super.__delattr__(name); + postDelattr(name); } - final void type___delattr__(String name) { - checkDelattr(); - super.__delattr__(name); + + void postDelattr(String name) { if (name == "__set__") { if (has_set && lookup("__set__") == null) { traverse_hierarchy(false, new OnType() { @@ -1168,7 +1172,7 @@ }); } } else if (name == "__delete__") { - if (has_set && lookup("__delete__") == null) { + if (has_delete && lookup("__delete__") == null) { traverse_hierarchy(false, new OnType() { public boolean onType(PyType type) { boolean absent = type.getDict().__finditem__("__delete__") == null; Modified: trunk/jython/tests/java/org/python/tests/Visible.java =================================================================== --- trunk/jython/tests/java/org/python/tests/Visible.java 2009-01-26 02:21:05 UTC (rev 5981) +++ trunk/jython/tests/java/org/python/tests/Visible.java 2009-01-26 03:10:36 UTC (rev 5982) @@ -58,4 +58,12 @@ public static int visibleStatic(int iinput, String input) { return EXTRA_ARG_PUBLIC_STATIC_METHOD; } + + public static int getVisibleStaticField() { + return visibleStaticField; + } + + public static void setVisibleStaticField(int newValue) { + visibleStaticField = newValue; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-26 03:36:33
|
Revision: 5983 http://jython.svn.sourceforge.net/jython/?rev=5983&view=rev Author: cgroves Date: 2009-01-26 03:36:25 +0000 (Mon, 26 Jan 2009) Log Message: ----------- Fix javatests Modified Paths: -------------- trunk/jython/src/org/python/core/PyNewWrapper.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/tests/java/org/python/expose/generate/TypeExposerTest.java Modified: trunk/jython/src/org/python/core/PyNewWrapper.java =================================================================== --- trunk/jython/src/org/python/core/PyNewWrapper.java 2009-01-26 03:10:36 UTC (rev 5982) +++ trunk/jython/src/org/python/core/PyNewWrapper.java 2009-01-26 03:36:25 UTC (rev 5983) @@ -28,15 +28,15 @@ PyType subtype, PyObject[] args, String[] keywords); - + public PyBuiltinCallable bind(PyObject self) { throw Py.SystemError("__new__ wrappers are already bound"); } - + public PyType getWrappedType() { return for_type; } - + public void setWrappedType(PyType type) { self = type; for_type = type; @@ -48,26 +48,22 @@ public PyObject __call__(PyObject[] args, String[] keywords) { int nargs = args.length; - if(nargs < 1 || nargs == keywords.length) { - throw Py.TypeError(for_type.fastGetName() - + ".__new__(): not enough arguments"); + if (nargs < 1 || nargs == keywords.length) { + throw Py.TypeError(for_type.fastGetName() + ".__new__(): not enough arguments"); } PyObject arg0 = args[0]; - if(!(arg0 instanceof PyType)) { - throw Py.TypeError(for_type.fastGetName() - + ".__new__(X): X is not a type object (" + if (!(arg0 instanceof PyType)) { + throw Py.TypeError(for_type.fastGetName() + ".__new__(X): X is not a type object (" + arg0.getType().fastGetName() + ")"); } PyType subtype = (PyType)arg0; - if(!subtype.isSubType(for_type)) { - throw Py.TypeError(for_type.fastGetName() + ".__new__(" - + subtype.fastGetName() + "): " + subtype.fastGetName() - + " is not a subtype of " + for_type.fastGetName()); + if (!subtype.isSubType(for_type)) { + throw Py.TypeError(for_type.fastGetName() + ".__new__(" + subtype.fastGetName() + "): " + + subtype.fastGetName() + " is not a subtype of " + for_type.fastGetName()); } - if(subtype.getStatic() != for_type) { - throw Py.TypeError(for_type.fastGetName() + ".__new__(" - + subtype.fastGetName() + ") is not safe, use " - + subtype.fastGetName() + ".__new__()"); + if (subtype.getStatic() != for_type) { + throw Py.TypeError(for_type.fastGetName() + ".__new__(" + subtype.fastGetName() + + ") is not safe, use " + subtype.fastGetName() + ".__new__()"); } PyObject[] rest = new PyObject[nargs - 1]; System.arraycopy(args, 1, rest, 0, nargs - 1); Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2009-01-26 03:10:36 UTC (rev 5982) +++ trunk/jython/src/org/python/core/PySystemState.java 2009-01-26 03:36:25 UTC (rev 5983) @@ -502,8 +502,9 @@ if (jarIndex >= 0) { int start = classpath.lastIndexOf(File.pathSeparator, jarIndex) + 1; root = classpath.substring(start, jarIndex); - } else { - // in case JYTHON_JAR is referenced from a MANIFEST inside another jar on the classpath + } else if (jarFileName != null) { + // in case JYTHON_JAR is referenced from a MANIFEST inside another jar on the + // classpath root = new File(jarFileName).getParent(); } } Modified: trunk/jython/tests/java/org/python/expose/generate/TypeExposerTest.java =================================================================== --- trunk/jython/tests/java/org/python/expose/generate/TypeExposerTest.java 2009-01-26 03:10:36 UTC (rev 5982) +++ trunk/jython/tests/java/org/python/expose/generate/TypeExposerTest.java 2009-01-26 03:36:25 UTC (rev 5983) @@ -2,9 +2,6 @@ import java.io.IOException; -import junit.framework.TestCase; - -import org.objectweb.asm.Type; import org.python.core.Py; import org.python.core.PyNewWrapper; import org.python.core.PyObject; @@ -38,8 +35,9 @@ .getResourceAsStream("org/python/expose/generate/TypeExposerTest$SimplestNew.class")); TypeBuilder te = etp.getTypeExposer().makeBuilder(); assertEquals(true, te.getIsBaseType()); - PyObject new_ = te.getDict(PyType.fromClass(SimplestNew.class)).__finditem__("__new__"); - assertEquals(Py.One, new_.__call__(PyType.fromClass(SimplestNew.class))); + PyType simplestType = PyType.fromClass(SimplestNew.class); + PyNewWrapper new_ = (PyNewWrapper)te.getDict(simplestType).__finditem__("__new__"); + assertEquals(Py.One, new_.new_impl(false, null, null, null)); } public void testCatchingDupes() throws IOException { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-02-19 20:16:25
|
Revision: 6040 http://jython.svn.sourceforge.net/jython/?rev=6040&view=rev Author: fwierzbicki Date: 2009-02-19 20:16:18 +0000 (Thu, 19 Feb 2009) Log Message: ----------- Our handling of writes after a seek beyond the end of cStringIO was not consistent with CPython (or even our own use of StringIO). Found while trying to get Mercurial to respond to "hg log". Modified Paths: -------------- trunk/jython/Lib/test/test_StringIO_jy.py trunk/jython/src/org/python/modules/cStringIO.java Modified: trunk/jython/Lib/test/test_StringIO_jy.py =================================================================== --- trunk/jython/Lib/test/test_StringIO_jy.py 2009-02-18 13:21:13 UTC (rev 6039) +++ trunk/jython/Lib/test/test_StringIO_jy.py 2009-02-19 20:16:18 UTC (rev 6040) @@ -20,6 +20,14 @@ f.write('hi') self.assertEquals(f.getvalue(), 'hehio') + #XXX: this should get pushed to CPython's test_StringIO + def test_write_past_end(self): + f = cStringIO.StringIO() + f.write("abcdef") + f.seek(10) + f.write("uvwxyz") + self.assertEqual(f.getvalue(), 'abcdef\x00\x00\x00\x00uvwxyz') + def test_main(): test_support.run_unittest(TestUnicodeInput) test_support.run_unittest(TestWrite) Modified: trunk/jython/src/org/python/modules/cStringIO.java =================================================================== --- trunk/jython/src/org/python/modules/cStringIO.java 2009-02-18 13:21:13 UTC (rev 6039) +++ trunk/jython/src/org/python/modules/cStringIO.java 2009-02-19 20:16:18 UTC (rev 6040) @@ -350,12 +350,17 @@ int newpos = spos + s.length(); - if (newpos > slen) { - buf.replace(spos, slen - spos, s); - buf.append(s.substring(slen)); + if (spos < slen) { + if (newpos > slen) { + buf.replace(spos, slen - spos, s); + buf.append(s.substring(slen)); + slen = newpos; + } else { + buf.replace(spos, spos + s.length(), s); + } + } else { + buf.append(s); slen = newpos; - } else { - buf.replace(spos, spos + s.length(), s); } buf.setLength(slen); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-24 05:45:43
|
Revision: 6046 http://jython.svn.sourceforge.net/jython/?rev=6046&view=rev Author: zyasoft Date: 2009-02-24 05:45:38 +0000 (Tue, 24 Feb 2009) Log Message: ----------- Merged revisions 5949,5952,5962,5964,5967-5970,5980,5984,5987-5989,5998-5999,6004-6005,6015-6022,6024-6030,6038,6041-6042 via svnmerge from https://jython.svn.sourceforge.net/svnroot/jython/branches/pbcvm ........ r5949 | zyasoft | 2009-01-20 06:56:46 -0700 (Tue, 20 Jan 2009) | 2 lines Initial commit. ........ r5952 | zyasoft | 2009-01-20 22:02:29 -0700 (Tue, 20 Jan 2009) | 3 lines Fixed binary and inplace bytecodes to use the proper methods. Added block support to support iteration. ........ r5962 | zyasoft | 2009-01-22 21:40:26 -0700 (Thu, 22 Jan 2009) | 3 lines Added support for try/except and try/finally blocks (and their combination). ........ r5964 | zyasoft | 2009-01-23 08:30:09 -0700 (Fri, 23 Jan 2009) | 2 lines Basic generators are almost supported. ........ r5967 | zyasoft | 2009-01-23 19:49:52 -0700 (Fri, 23 Jan 2009) | 2 lines Now supports generators, via the standard PyGenerator protocol. ........ r5968 | zyasoft | 2009-01-23 21:36:06 -0700 (Fri, 23 Jan 2009) | 2 lines Added support for keyword args, *arg, and **kwarg calling conventions. ........ r5969 | zyasoft | 2009-01-24 09:47:59 -0700 (Sat, 24 Jan 2009) | 3 lines Added support for basic coroutines (no support for throw) and generator expressions. ........ r5970 | zyasoft | 2009-01-24 11:02:37 -0700 (Sat, 24 Jan 2009) | 2 lines Supports throwing exceptions into generators. ........ r5980 | zyasoft | 2009-01-25 18:19:12 -0700 (Sun, 25 Jan 2009) | 4 lines Properly handles *args, **kwargs for the receiver function. func_code can now be set to a PyBytecode (or other extender of PyBaseCode). Turned off debugging by default for PyBytecode objects. ........ r5984 | zyasoft | 2009-01-25 22:02:21 -0700 (Sun, 25 Jan 2009) | 2 lines Added extract tool (to be run by CPython) for creating test modules. ........ r5987 | zyasoft | 2009-01-26 18:45:48 -0700 (Mon, 26 Jan 2009) | 2 lines Fixed raising of exceptions and PyStack.rot ........ r5988 | zyasoft | 2009-01-26 19:16:49 -0700 (Mon, 26 Jan 2009) | 2 lines Fixed opcode support for LOAD/STORE/DELETE_NAME and BUILD_CLASS. ........ r5989 | zyasoft | 2009-01-26 19:26:20 -0700 (Mon, 26 Jan 2009) | 2 lines Fixed RAISE_VARARGS opcode to raise exceptions properly. ........ r5998 | zyasoft | 2009-01-28 20:44:58 -0700 (Wed, 28 Jan 2009) | 3 lines extract.py now creates modules where codeobjects respect their dependency relationships (via a tsort). ........ r5999 | zyasoft | 2009-01-29 07:24:33 -0700 (Thu, 29 Jan 2009) | 6 lines Extract script now processes most/all of the test.test_* modules with a test_main and importable by CPython. May want to consider generalizing support for instance methods and closure setup with respect to new.function (= PyFunction), but this seems purely a testing nicety for top-level defs. ........ r6004 | zyasoft | 2009-02-01 01:12:13 -0700 (Sun, 01 Feb 2009) | 3 lines From http://svn.python.org/projects/python/branches/release25-maint/Lib/test/test_marshal@27825 ........ r6005 | zyasoft | 2009-02-01 01:24:06 -0700 (Sun, 01 Feb 2009) | 13 lines Added _marshal, a Java implementation of the Python module, and made current. test_marshal now passes (with minor modifications around GC and floating point accuracy on to/from string representation), except for support of code objects. That's next. Pulled IOFile (now PyIOFile) from cPickle to share its duck typing with _marshal A historical note: from what I can discern in the log, the original marshal.py was written by Guido van Rossum specifically for "JPython" in 1997, one of the few bits he apparently did. Now it survives only as a shell, to import in _marshal. ........ r6015 | zyasoft | 2009-02-05 20:50:10 -0700 (Thu, 05 Feb 2009) | 5 lines Changed read/write binary_float so that it doesn't go through struct but instead j.l.Double's support for converting to/from bits. This also resolves endian ordering issues so that it follows the native endian ordering. ........ r6016 | zyasoft | 2009-02-06 00:07:45 -0700 (Fri, 06 Feb 2009) | 7 lines Fixed some cellvar/freevar nested scope issues, with work to continue. Added a slightly modified version of pycimport.py from Tobias' pyasm implementation in the sandbox. This, in conjunction with compileall (run from CPython; compileall.compile_dir against the unit tests) is allowing a significant fraction of the regrtest to run against PBC-VM. ........ r6017 | zyasoft | 2009-02-06 00:42:15 -0700 (Fri, 06 Feb 2009) | 2 lines Fixed slice, exec support. ........ r6018 | zyasoft | 2009-02-06 21:04:54 -0700 (Fri, 06 Feb 2009) | 2 lines Fixed stack ops (DUP_TOPX, ROT_THREE, ROT_FOUR), INPLACE_POWER. ........ r6019 | zyasoft | 2009-02-06 23:29:37 -0700 (Fri, 06 Feb 2009) | 5 lines Fixed IMPORT_STAR for nested modules. sys.exc_info now returns Py.None for the traceback (this fixes an issue in PBC where null is being used as both a sentinel value by __getitem__ AND an actual value for exception handling). ........ r6020 | zyasoft | 2009-02-07 10:47:19 -0700 (Sat, 07 Feb 2009) | 2 lines Fixes nested scope treatment of free variables. ........ r6021 | zyasoft | 2009-02-07 11:14:33 -0700 (Sat, 07 Feb 2009) | 2 lines Further refinement of nested scopes. ........ r6022 | zyasoft | 2009-02-07 14:26:31 -0700 (Sat, 07 Feb 2009) | 3 lines Fixed control flow by pushing the wrapped Why onto the stack (instead of its string representation from the earliest version of this code). ........ r6024 | zyasoft | 2009-02-10 20:11:10 -0700 (Tue, 10 Feb 2009) | 7 lines Support tostring/fromstring of unsigned types so that they can be stored in the same size as their signed representation. This fixes an issues with peak.util.assembler where it expects that unsigned bytes (typecode 'B') take one byte to store and therefore are directly interoperable with co_code. ........ r6025 | zyasoft | 2009-02-11 21:38:04 -0700 (Wed, 11 Feb 2009) | 2 lines Beginning of PBC compilation support. Pretty much a shell for now. ........ r6026 | zyasoft | 2009-02-14 02:23:58 -0700 (Sat, 14 Feb 2009) | 7 lines Now interns names in co_names, etc., when unmarshalling, which fixes equality tests on special case like __class__, __dict__, etc. Fix instanceof test in eval and exec so that it looks at PyBaseCode, not PyTableCode. Also, exec cannot be called with Py.None instead of null. Fixes test_scope. ........ r6027 | zyasoft | 2009-02-14 03:44:17 -0700 (Sat, 14 Feb 2009) | 3 lines Set the traceback when intercepting an exception. Set __doc__ strings for functions from the constant pool (if available). ........ r6028 | zyasoft | 2009-02-14 04:17:17 -0700 (Sat, 14 Feb 2009) | 3 lines LOAD_DEREF needs to do the same lookup as LOAD_CLOSURE. Populate doc strings for MAKE_CLOSURE. ........ r6029 | zyasoft | 2009-02-14 04:58:48 -0700 (Sat, 14 Feb 2009) | 3 lines Fixed WITH_CLEANUP so that it properly calls __exit__ with the exception components off the stack. ........ r6030 | zyasoft | 2009-02-14 12:17:04 -0700 (Sat, 14 Feb 2009) | 3 lines Fixed UNPACK_SEQUENCE so that ValueError is raised if too few/too many values to unpack. ........ r6038 | zyasoft | 2009-02-17 17:06:55 -0700 (Tue, 17 Feb 2009) | 8 lines Added support for code.getlineno (using co_lnotab), co_code, co_consts, co_lnotab. co_code and co_lnotab now use byte[] for a more compact representation and then manage accessing as if it were an unsigned representation. This enables a good chunk of the peak.util.assembler unit tests to pass; the remainder seem to have a dictionary traversal dependency. ........ r6041 | zyasoft | 2009-02-22 07:40:49 -0700 (Sun, 22 Feb 2009) | 4 lines Inlined PyTableCode#interpret into #call(PyFrame,PyClosure) (which restores this method to what it was before the PBC-VM work). This change restores the performance as tested by test/pystone.py. ........ r6042 | zyasoft | 2009-02-23 21:25:13 -0700 (Mon, 23 Feb 2009) | 8 lines LineCache implementation to support efficient setline edge detection, as necessary for tracing. No longer looks up the ThreadState twice, in the caller of PyBytecode#interpret and interpret itself, so this should provide for some optimization. ........ Modified Paths: -------------- trunk/jython/Lib/marshal.py trunk/jython/Lib/new.py trunk/jython/Lib/test/test_array.py trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/PyArray.java trunk/jython/src/org/python/core/PyFrame.java trunk/jython/src/org/python/core/PyFunction.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/PyTableCode.java trunk/jython/src/org/python/core/__builtin__.java trunk/jython/src/org/python/core/imp.java trunk/jython/src/org/python/modules/Setup.java trunk/jython/src/org/python/modules/cPickle.java trunk/jython/src/org/python/modules/struct.java Added Paths: ----------- trunk/jython/Lib/pycimport.py trunk/jython/Lib/test/test_marshal.py trunk/jython/Tools/pbcvm/ trunk/jython/Tools/pbcvm/extract.py trunk/jython/src/org/python/compiler/pbc/ trunk/jython/src/org/python/compiler/pbc/Bytecode.java trunk/jython/src/org/python/compiler/pbc/BytecodeCompiler.java trunk/jython/src/org/python/core/Opcode.java trunk/jython/src/org/python/core/PyBaseCode.java trunk/jython/src/org/python/core/PyBytecode.java trunk/jython/src/org/python/modules/PyIOFile.java trunk/jython/src/org/python/modules/PyIOFileFactory.java trunk/jython/src/org/python/modules/_marshal.java Removed Paths: ------------- trunk/jython/Tools/pbcvm/extract.py trunk/jython/src/org/python/compiler/pbc/Bytecode.java trunk/jython/src/org/python/compiler/pbc/BytecodeCompiler.java Property Changed: ---------------- trunk/jython/ Property changes on: trunk/jython ___________________________________________________________________ Modified: svnmerge-integrated - /branches/pbcvm:1-5948 + /branches/pbcvm:1-6045 Modified: trunk/jython/Lib/marshal.py =================================================================== --- trunk/jython/Lib/marshal.py 2009-02-24 05:04:05 UTC (rev 6045) +++ trunk/jython/Lib/marshal.py 2009-02-24 05:45:38 UTC (rev 6046) @@ -5,332 +5,24 @@ """ -import StringIO -import string -from types import * -try: - import new -except ImportError: - new = None +import cStringIO +from _marshal import Marshaller, Unmarshaller -TYPE_NULL = '0' -TYPE_NONE = 'N' -TYPE_FALSE = 'F' -TYPE_TRUE = 'T' -TYPE_ELLIPSIS = '.' -TYPE_INT = 'i' -TYPE_INT64 = 'I' -TYPE_FLOAT = 'f' -TYPE_COMPLEX = 'x' -TYPE_LONG = 'l' -TYPE_STRING = 's' -TYPE_TUPLE = '(' -TYPE_LIST = '[' -TYPE_DICT = '{' -TYPE_CODE = 'c' -TYPE_UNKNOWN = '?' +def dump(x, f, version=2): + Marshaller(f, version).dump(x) +# XXX - added just for debugging. remove! +def load(f, debug=False): + u = Unmarshaller(f) + if debug: + u._debug() + return u.load() -class Marshaller: - - dispatch = {} - - def __init__(self, f): - self.f = f - - def dump(self, x): - self.dispatch[type(x)](self, x) - - def w_long64(self, x): - self.w_long(x) - self.w_long(x>>32) - - def w_long(self, x): - write = self.f.write - write(chr((x) & 0xff)) - write(chr((x>> 8) & 0xff)) - write(chr((x>>16) & 0xff)) - write(chr((x>>24) & 0xff)) - - def w_short(self, x): - write = self.f.write - write(chr((x) & 0xff)) - write(chr((x>> 8) & 0xff)) - - def dump_none(self, x): - self.f.write(TYPE_NONE) - dispatch[NoneType] = dump_none - - def dump_bool(self, x): - if x: - self.f.write(TYPE_TRUE) - else: - self.f.write(TYPE_FALSE) - dispatch[BooleanType] = dump_bool - - def dump_ellipsis(self, x): - self.f.write(TYPE_ELLIPSIS) - try: - dispatch[EllipsisType] = dump_ellipsis - except NameError: - pass - - def dump_int(self, x): - y = x>>31 - if y and y != -1: - self.f.write(TYPE_INT64) - self.w_long64(x) - else: - self.f.write(TYPE_INT) - self.w_long(x) - dispatch[IntType] = dump_int - - def dump_long(self, x): - self.f.write(TYPE_LONG) - sign = 1 - if x < 0: - sign = -1 - x = -x - digits = [] - while x: - digits.append(x & 0x7FFF) - x = x>>15 - self.w_long(len(digits) * sign) - for d in digits: - self.w_short(d) - dispatch[LongType] = dump_long - - def dump_float(self, x): - write = self.f.write - write(TYPE_FLOAT) - s = `x` - write(chr(len(s))) - write(s) - dispatch[FloatType] = dump_float - - def dump_complex(self, x): - write = self.f.write - write(TYPE_COMPLEX) - s = `x.real` - write(chr(len(s))) - write(s) - s = `x.imag` - write(chr(len(s))) - write(s) - try: - dispatch[ComplexType] = dump_complex - except NameError: - pass - - def dump_string(self, x): - self.f.write(TYPE_STRING) - self.w_long(len(x)) - self.f.write(x) - dispatch[StringType] = dump_string - - def dump_tuple(self, x): - self.f.write(TYPE_TUPLE) - self.w_long(len(x)) - for item in x: - self.dump(item) - dispatch[TupleType] = dump_tuple - - def dump_list(self, x): - self.f.write(TYPE_LIST) - self.w_long(len(x)) - for item in x: - self.dump(item) - dispatch[ListType] = dump_list - - def dump_dict(self, x): - self.f.write(TYPE_DICT) - for key, value in x.items(): - self.dump(key) - self.dump(value) - self.f.write(TYPE_NULL) - dispatch[DictionaryType] = dump_dict - - def dump_code(self, x): - self.f.write(TYPE_CODE) - self.w_short(x.co_argcount) - self.w_short(x.co_nlocals) - self.w_short(x.co_stacksize) - self.w_short(x.co_flags) - self.dump(x.co_code) - self.dump(x.co_consts) - self.dump(x.co_names) - self.dump(x.co_varnames) - self.dump(x.co_filename) - self.dump(x.co_name) - self.w_short(x.co_firstlineno) - self.dump(x.co_lnotab) - try: - dispatch[CodeType] = dump_code - except NameError: - pass - - -class NULL: - pass - -class Unmarshaller: - - dispatch = {} - - def __init__(self, f): - self.f = f - - def load(self): - c = self.f.read(1) - if not c: - raise EOFError - return self.dispatch[c](self) - - def r_short(self): - read = self.f.read - lo = ord(read(1)) - hi = ord(read(1)) - x = lo | (hi<<8) - if x & 0x8000: - x = x - 0x10000 - return x - - def r_long(self): - read = self.f.read - a = ord(read(1)) - b = ord(read(1)) - c = ord(read(1)) - d = ord(read(1)) - # convert unsigned d to signed to avoid d << 24 possibly - # overflowing into a long value - if d > 127: - d -= 256 - x = a | (b<<8) | (c<<16) | (d<<24) - if x & 0x80000000 and x > 0: - x = string.atoi(x - 0x100000000L) - return x - - def r_long64(self): - a = self.r_long() - b = self.r_long() - return a | (b<<32) - - def load_null(self): - return NULL - dispatch[TYPE_NULL] = load_null - - def load_none(self): - return None - dispatch[TYPE_NONE] = load_none - - def load_False(self): - return False - dispatch[TYPE_FALSE] = load_False - - def load_True(self): - return True - dispatch[TYPE_TRUE] = load_True - - def load_ellipsis(self): - return EllipsisType - dispatch[TYPE_ELLIPSIS] = load_ellipsis - - def load_int(self): - return self.r_long() - dispatch[TYPE_INT] = load_int - - def load_int64(self): - return self.r_long64() - dispatch[TYPE_INT64] = load_int64 - - def load_long(self): - size = self.r_long() - sign = 1 - if size < 0: - sign = -1 - size = -size - x = 0L - for i in range(size): - d = self.r_short() - x = x | (d<<(i*15L)) - return x * sign - dispatch[TYPE_LONG] = load_long - - def load_float(self): - n = ord(self.f.read(1)) - s = self.f.read(n) - return string.atof(s) - dispatch[TYPE_FLOAT] = load_float - - def load_complex(self): - n = ord(self.f.read(1)) - s = self.f.read(n) - real = float(s) - n = ord(self.f.read(1)) - s = self.f.read(n) - imag = float(s) - return complex(real, imag) - dispatch[TYPE_COMPLEX] = load_complex - - def load_string(self): - n = self.r_long() - return self.f.read(n) - dispatch[TYPE_STRING] = load_string - - def load_tuple(self): - return tuple(self.load_list()) - dispatch[TYPE_TUPLE] = load_tuple - - def load_list(self): - n = self.r_long() - list = [] - for i in range(n): - list.append(self.load()) - return list - dispatch[TYPE_LIST] = load_list - - def load_dict(self): - d = {} - while 1: - key = self.load() - if key is NULL: - break - value = self.load() - d[key] = value - return d - dispatch[TYPE_DICT] = load_dict - - def load_code(self): - argcount = self.r_short() - nlocals = self.r_short() - stacksize = self.r_short() - flags = self.r_short() - code = self.load() - consts = self.load() - names = self.load() - varnames = self.load() - filename = self.load() - name = self.load() - firstlineno = self.r_short() - lnotab = self.load() - if not new: - raise RuntimeError, "can't unmarshal code objects; no 'new' module" - return new.code(argcount, nlocals, stacksize, flags, code, consts, - names, varnames, filename, name, firstlineno, lnotab) - dispatch[TYPE_CODE] = load_code - - -def dump(x, f): - Marshaller(f).dump(x) - -def load(f): - return Unmarshaller(f).load() - -def dumps(x): - f = StringIO.StringIO() - dump(x, f) +def dumps(x, version=2): + f = cStringIO.StringIO() + dump(x, f, version) return f.getvalue() def loads(s): - f = StringIO.StringIO(s) + f = cStringIO.StringIO(s) return load(f) Modified: trunk/jython/Lib/new.py =================================================================== --- trunk/jython/Lib/new.py 2009-02-24 05:04:05 UTC (rev 6045) +++ trunk/jython/Lib/new.py 2009-02-24 05:45:38 UTC (rev 6046) @@ -20,3 +20,5 @@ # from types import CodeType as code #except ImportError: # pass + +from org.python.core import PyBytecode as code Copied: trunk/jython/Lib/pycimport.py (from rev 6042, branches/pbcvm/Lib/pycimport.py) =================================================================== --- trunk/jython/Lib/pycimport.py (rev 0) +++ trunk/jython/Lib/pycimport.py 2009-02-24 05:45:38 UTC (rev 6046) @@ -0,0 +1,84 @@ +import sys +import os + +from org.python.core import imp as _imp, PyFrame as _Frame, Py as _Py +from marshal import Unmarshaller + +__debugging__ = False + +def __readPycHeader(file): + def read(): + return ord(file.read(1)) + magic = read() | (read()<<8) + if not ( file.read(1) == '\r' and file.read(1) == '\n' ): + raise TypeError("not valid pyc-file") + mtime = read() | (read()<<8) | (read()<<16) | (read()<<24) + return magic, mtime + +def __makeModule(name, code, path): + module = _imp.addModule(name) + builtins = _Py.getSystemState().builtins + frame = _Frame(code, module.__dict__, module.__dict__, builtins) + module.__file__ = path + code.call(frame) # execute module code + return module + +class __Importer(object): + def __init__(self, path): + if __debugging__: print "Importer invoked" + self.__path = path + def find_module(self, fullname, path=None): + if __debugging__: + print "Importer.find_module(fullname=%s, path=%s)" % ( + repr(fullname), repr(path)) + path = fullname.split('.') + filename = path[-1] + path = path[:-1] + pycfile = os.path.join(self.__path, *(path + [filename + '.pyc'])) + pyfile = os.path.join(self.__path, *(path + [filename + '.py'])) + if os.path.exists(pycfile): + f = open(pycfile, 'rb') + try: + magic, mtime = __readPycHeader(f) + except: + return None # abort! not a valid pyc-file + f.close() + if os.path.exists(pyfile): + pytime = os.stat(pyfile).st_mtime + if pytime > mtime: + return None # abort! py-file was newer + return self + else: + return None # abort! pyc-file does not exist + def load_module(self, fullname): + path = fullname.split('.') + path[-1] += '.pyc' + filename = os.path.join(self.__path, *path) + f = open(filename, 'rb') + magic, mtime = __readPycHeader(f) + #code = Unmarshaller(f, magic=magic).load() + code = Unmarshaller(f).load() + if __debugging__: print "Successfully loaded:", fullname + return __makeModule( fullname, code, filename ) + +class __MetaImporter(object): + def __init__(self): + self.__importers = {} + def find_module(self, fullname, path): + if __debugging__: print "MetaImporter.find_module(%s, %s)" % ( + repr(fullname), repr(path)) + for _path in sys.path: + if _path not in self.__importers: + try: + self.__importers[_path] = __Importer(_path) + except: + self.__importers[_path] = None + importer = self.__importers[_path] + if importer is not None: + loader = importer.find_module(fullname, path) + if loader is not None: + return loader + else: + return None + +sys.meta_path.insert(0, __MetaImporter()) Modified: trunk/jython/Lib/test/test_array.py =================================================================== --- trunk/jython/Lib/test/test_array.py 2009-02-24 05:04:05 UTC (rev 6045) +++ trunk/jython/Lib/test/test_array.py 2009-02-24 05:45:38 UTC (rev 6046) @@ -213,7 +213,7 @@ self.assertRaises(TypeError, b.fromstring, 42) b.fromstring(a.tostring()) self.assertEqual(a, b) - if a.itemsize>1: + if a.itemsize>1 and self.typecode not in ('b', 'B'): self.assertRaises(ValueError, b.fromstring, "x") def test_repr(self): Copied: trunk/jython/Lib/test/test_marshal.py (from rev 6042, branches/pbcvm/Lib/test/test_marshal.py) =================================================================== --- trunk/jython/Lib/test/test_marshal.py (rev 0) +++ trunk/jython/Lib/test/test_marshal.py 2009-02-24 05:45:38 UTC (rev 6046) @@ -0,0 +1,264 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-1 -*- + +from __future__ import with_statement +from test import test_support +import marshal +import sys +import unittest +import os + +# the original had incorrect semantics for non-refcounting GCs: +# marshal.dump(expected, file(test_support.TESTFN, "wb")) +# got = marshal.load(file(test_support.TESTFN, "rb")) + +def roundtrip(item): + with open(test_support.TESTFN, "wb") as test_file: + marshal.dump(item, test_file) + with open(test_support.TESTFN, "rb") as test_file: + got = marshal.load(file(test_support.TESTFN, "rb")) #, debug=True) + return got + + +class IntTestCase(unittest.TestCase): + def test_ints(self): + # Test the full range of Python ints. + n = sys.maxint + while n: + for expected in (-n, n): + s = marshal.dumps(expected) + got = marshal.loads(s) + self.assertEqual(expected, got) + self.assertEqual(expected, roundtrip(expected)) + n = n >> 1 + os.unlink(test_support.TESTFN) + + def test_int64(self): + # Simulate int marshaling on a 64-bit box. This is most interesting if + # we're running the test on a 32-bit box, of course. + + def to_little_endian_string(value, nbytes): + bytes = [] + for i in range(nbytes): + bytes.append(chr(value & 0xff)) + value >>= 8 + return ''.join(bytes) + + maxint64 = (1L << 63) - 1 + minint64 = -maxint64-1 + + for base in maxint64, minint64, -maxint64, -(minint64 >> 1): + while base: + s = 'I' + to_little_endian_string(base, 8) + got = marshal.loads(s) + self.assertEqual(base, got) + if base == -1: # a fixed-point for shifting right 1 + base = 0 + else: + base >>= 1 + + def test_bool(self): + for b in (True, False): + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(b, new) + self.assertEqual(type(b), type(new)) + new = roundtrip(b) + self.assertEqual(b, new) + self.assertEqual(type(b), type(new)) + +class FloatTestCase(unittest.TestCase): + def test_floats(self): + # Test a few floats + small = 1e-25 + n = sys.maxint * 3.7e250 + while n > small: + for expected in (-n, n): + f = float(expected) + s = marshal.dumps(f) + got = marshal.loads(s) + self.assertEqual(f, got) + got = roundtrip(f) + self.assertEqual(f, got) + n /= 123.4567 + + f = 0.0 + s = marshal.dumps(f, 2) + got = marshal.loads(s) + self.assertEqual(f, got) + # and with version <= 1 (floats marshalled differently then) + s = marshal.dumps(f, 1) + got = marshal.loads(s) + self.assertEqual(f, got) + + n = sys.maxint * 3.7e-250 + while n < small: + for expected in (-n, n): + f = float(expected) + + s = marshal.dumps(f) + got = marshal.loads(s) + self.assertEqual(f, got) + + s = marshal.dumps(f, 1) + got = marshal.loads(s) + if test_support.is_jython: + self.assertAlmostEqual(f, got) + else: + self.assertEqual(f, got) + + got = roundtrip(f) + self.assertEqual(f, got) + + # XXX - not certain what this extra arg to dump is! + #marshal.dump(f, file(test_support.TESTFN, "wb"), 1) + #got = marshal.load(file(test_support.TESTFN, "rb")) + #self.assertEqual(f, got) + n *= 123.4567 + os.unlink(test_support.TESTFN) + +class StringTestCase(unittest.TestCase): + def test_unicode(self): + for s in [u"", u"Andr\xE8 Previn", u"abc", u" "*10000]: + new = marshal.loads(marshal.dumps(s)) + self.assertEqual(s, new) + self.assertEqual(type(s), type(new)) + new = roundtrip(s) + self.assertEqual(s, new) + self.assertEqual(type(s), type(new)) + os.unlink(test_support.TESTFN) + + def test_string(self): + for s in ["", "Andr\xE8 Previn", "abc", " "*10000]: + new = marshal.loads(marshal.dumps(s)) + self.assertEqual(s, new) + self.assertEqual(type(s), type(new)) + new = roundtrip(s) + self.assertEqual(s, new) + self.assertEqual(type(s), type(new)) + os.unlink(test_support.TESTFN) + + if not test_support.is_jython: + def test_buffer(self): + for s in ["", "Andr\xE8 Previn", "abc", " "*10000]: + b = buffer(s) + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(s, new) + new = roundtrip(b) + self.assertEqual(s, new) + os.unlink(test_support.TESTFN) + +class ExceptionTestCase(unittest.TestCase): + def test_exceptions(self): + new = marshal.loads(marshal.dumps(StopIteration)) + self.assertEqual(StopIteration, new) + +class CodeTestCase(unittest.TestCase): + if not test_support.is_jython: # XXX - need to use the PBC compilation backend, which doesn't exist yet + def test_code(self): + co = ExceptionTestCase.test_exceptions.func_code + new = marshal.loads(marshal.dumps(co)) + self.assertEqual(co, new) + +class ContainerTestCase(unittest.TestCase): + d = {'astring': 'fo...@ba...z.spam', + 'afloat': 7283.43, + 'anint': 2**20, + 'ashortlong': 2L, + 'alist': ['.zyx.41'], + 'atuple': ('.zyx.41',)*10, + 'aboolean': False, + 'aunicode': u"Andr\xE8 Previn" + } + def test_dict(self): + new = marshal.loads(marshal.dumps(self.d)) + self.assertEqual(self.d, new) + new = roundtrip(self.d) + self.assertEqual(self.d, new) + os.unlink(test_support.TESTFN) + + def test_list(self): + lst = self.d.items() + new = marshal.loads(marshal.dumps(lst)) + self.assertEqual(lst, new) + new = roundtrip(lst) + self.assertEqual(lst, new) + os.unlink(test_support.TESTFN) + + def test_tuple(self): + t = tuple(self.d.keys()) + new = marshal.loads(marshal.dumps(t)) + self.assertEqual(t, new) + new = roundtrip(t) + self.assertEqual(t, new) + os.unlink(test_support.TESTFN) + + def test_sets(self): + for constructor in (set, frozenset): + t = constructor(self.d.keys()) + new = marshal.loads(marshal.dumps(t)) + self.assertEqual(t, new) + self.assert_(isinstance(new, constructor)) + self.assertNotEqual(id(t), id(new)) + new = roundtrip(t) + self.assertEqual(t, new) + os.unlink(test_support.TESTFN) + +class BugsTestCase(unittest.TestCase): + def test_bug_5888452(self): + # Simple-minded check for SF 588452: Debug build crashes + marshal.dumps([128] * 1000) + + def test_patch_873224(self): + self.assertRaises(Exception, marshal.loads, '0') + self.assertRaises(Exception, marshal.loads, 'f') + self.assertRaises(Exception, marshal.loads, marshal.dumps(5L)[:-1]) + + def test_version_argument(self): + # Python 2.4.0 crashes for any call to marshal.dumps(x, y) + self.assertEquals(marshal.loads(marshal.dumps(5, 0)), 5) + self.assertEquals(marshal.loads(marshal.dumps(5, 1)), 5) + + def test_fuzz(self): + # simple test that it's at least not *totally* trivial to + # crash from bad marshal data + for c in [chr(i) for i in range(256)]: + try: + marshal.loads(c) + except Exception: + pass + + def test_loads_recursion(self): + s = 'c' + ('X' * 4*4) + '{' * 2**20 + self.assertRaises(ValueError, marshal.loads, s) + + def test_recursion_limit(self): + # Create a deeply nested structure. + head = last = [] + # The max stack depth should match the value in Python/marshal.c. + MAX_MARSHAL_STACK_DEPTH = 2000 + for i in range(MAX_MARSHAL_STACK_DEPTH - 2): + last.append([0]) + last = last[-1] + + # Verify we don't blow out the stack with dumps/load. + data = marshal.dumps(head) + new_head = marshal.loads(data) + # Don't use == to compare objects, it can exceed the recursion limit. + self.assertEqual(len(new_head), len(head)) + self.assertEqual(len(new_head[0]), len(head[0])) + self.assertEqual(len(new_head[-1]), len(head[-1])) + + last.append([0]) + self.assertRaises(ValueError, marshal.dumps, head) + +def test_main(): + test_support.run_unittest(IntTestCase, + FloatTestCase, + StringTestCase, + CodeTestCase, + ContainerTestCase, + ExceptionTestCase, + BugsTestCase) + +if __name__ == "__main__": + test_main() Deleted: trunk/jython/Tools/pbcvm/extract.py =================================================================== --- branches/pbcvm/Tools/pbcvm/extract.py 2009-02-24 04:25:13 UTC (rev 6042) +++ trunk/jython/Tools/pbcvm/extract.py 2009-02-24 05:45:38 UTC (rev 6046) @@ -1,141 +0,0 @@ -"""Given a module, generates a new module where all functions that are - not builtin (including within classes) have their func_code pointed - to a PyBytecode constructor. This enables CPython to generate for - Jython the desired PBC. -""" - -from __future__ import with_statement -import inspect -import networkx # add dependency to a setup script? probably overkill -import sys -from collections import defaultdict - -attrs = ["co_" + x for x in """ - argcount nlocals stacksize flags - code consts names varnames - filename name firstlineno lnotab - freevars cellvars -""".split()] # add - -ROOT = object() - -class Extract(object): - - def __init__(self, mod, writer): - self.mod = mod - self.writer = writer - self.codeobjs = {} - self.codeobjs_names = {} - self.counters = defaultdict(int) - self.depend = networkx.DiGraph() - - def extract(self): - mod = self.mod - writer = self.writer - functionobjs = self.candidate_functions() - for name, f in functionobjs: - self.extract_code_obj(f) - - print >> writer, "from %s import *" % mod.__name__ - print >> writer, "from org.python.core import PyBytecode" - print >> writer - print >> writer, "_codeobjs = {}" - print >> writer - - objs = networkx.topological_sort(self.depend) - for obj in objs: - if not inspect.iscode(obj): - continue - name = self.codeobjs_names[obj] - print >> writer, "_codeobjs[%r] = %s" % (name, self.codeobjs[obj]) - print >> writer - for name, f in functionobjs: - # this may be a Jython diff, need to determine further; need to check if im_func or not on the object - print >> writer, "try: %s.func_code = _codeobjs[%r]" % (name, self.codeobjs_names[f.func_code]) - print >> writer, "except (AttributeError, ValueError): pass" # ignore setting cells, im_func, etc... %s.im_func.func_code = _codeobjs[%r]" % (name, self.codeobjs_names[f.func_code]) - - print >> writer - print >> writer, 'if __name__ == "__main__":' - print >> writer, ' test_main()' - - def candidate_functions(self): - """functions and methods we will retrieve code objects""" - - mod = self.mod - functions = inspect.getmembers(mod, inspect.isfunction) - functions = [(name, f) for (name, f) in functions if not inspect.isbuiltin(f) and name != "test_main"] - - classes = inspect.getmembers(mod, inspect.isclass) - for classname, cls in classes: - for methodname, method in inspect.getmembers(cls, inspect.ismethod): - if inspect.getmodule(method) == mod: - functions.append(("%s.%s" % (classname, methodname), method)) - return functions - - def extract_code_obj(self, f_or_code): - if inspect.iscode(f_or_code): - code = f_or_code - else: - code = f_or_code.func_code - self.extract_def(code) - - def extract_def(self, code): - if code in self.codeobjs_names: - #print >> sys.stderr, "Already seen", code - return "_codeobjs[%r]" % (self.codeobjs_names[code],) - - co_name = code.co_name - #print >> sys.stderr, "Processing", code - name = co_name + "." + str(self.counters[co_name]) - self.counters[co_name] += 1 - self.codeobjs_names[code] = name - values = [] - self.depend.add_edge(code, ROOT) - for attr in attrs: - # treat co_consts specially - maybe also need to use pickling in case repr is not suitable - if attr == 'co_consts': - co_consts = [] - for const in getattr(code, attr): - if inspect.iscode(const): - #print >> sys.stderr, "Extracting code const " + str(const) - co_consts.append(self.extract_def(const)) - self.depend.add_edge(const, code) - else: - co_consts.append(repr(const)) - values.append((attr, "["+', '.join(co_consts)+"]")) - else: - values.append((attr, repr(getattr(code, attr)))) - self.codeobjs[code] = "PyBytecode(\n" + '\n'.join([' '* 4 + v + ', # ' + attr for (attr, v) in values])+"\n )" - return "_codeobjs[%r]" % (name,) - - -# for now, just use the cwd -def import_modules(path): - import glob - import os.path - - sys.path.insert(0, path) - for name in sorted(glob.iglob("test/test_*.py")): - modname = os.path.splitext(os.path.basename(name))[0] - qualified_name = "test." + modname - print "Trying", qualified_name - try: - topmod = __import__(qualified_name) - except Exception, e: - print "Could not import", qualified_name, ":", repr(e) - continue - mod = getattr(topmod, modname) - try: - mod.test_main - except AttributeError, e: - print "No test_main in", qualified_name - continue - - output_name = "test/" + modname + "_pbc.py" - with open(output_name, "w") as f: - print "Extracting", name, "to", output_name - Extract(mod, f).extract() - -if __name__ == '__main__': - path = modname = sys.argv[1] - import_modules(path) Copied: trunk/jython/Tools/pbcvm/extract.py (from rev 6042, branches/pbcvm/Tools/pbcvm/extract.py) =================================================================== --- trunk/jython/Tools/pbcvm/extract.py (rev 0) +++ trunk/jython/Tools/pbcvm/extract.py 2009-02-24 05:45:38 UTC (rev 6046) @@ -0,0 +1,141 @@ +"""Given a module, generates a new module where all functions that are + not builtin (including within classes) have their func_code pointed + to a PyBytecode constructor. This enables CPython to generate for + Jython the desired PBC. +""" + +from __future__ import with_statement +import inspect +import networkx # add dependency to a setup script? probably overkill +import sys +from collections import defaultdict + +attrs = ["co_" + x for x in """ + argcount nlocals stacksize flags + code consts names varnames + filename name firstlineno lnotab + freevars cellvars +""".split()] # add + +ROOT = object() + +class Extract(object): + + def __init__(self, mod, writer): + self.mod = mod + self.writer = writer + self.codeobjs = {} + self.codeobjs_names = {} + self.counters = defaultdict(int) + self.depend = networkx.DiGraph() + + def extract(self): + mod = self.mod + writer = self.writer + functionobjs = self.candidate_functions() + for name, f in functionobjs: + self.extract_code_obj(f) + + print >> writer, "from %s import *" % mod.__name__ + print >> writer, "from org.python.core import PyBytecode" + print >> writer + print >> writer, "_codeobjs = {}" + print >> writer + + objs = networkx.topological_sort(self.depend) + for obj in objs: + if not inspect.iscode(obj): + continue + name = self.codeobjs_names[obj] + print >> writer, "_codeobjs[%r] = %s" % (name, self.codeobjs[obj]) + print >> writer + for name, f in functionobjs: + # this may be a Jython diff, need to determine further; need to check if im_func or not on the object + print >> writer, "try: %s.func_code = _codeobjs[%r]" % (name, self.codeobjs_names[f.func_code]) + print >> writer, "except (AttributeError, ValueError): pass" # ignore setting cells, im_func, etc... %s.im_func.func_code = _codeobjs[%r]" % (name, self.codeobjs_names[f.func_code]) + + print >> writer + print >> writer, 'if __name__ == "__main__":' + print >> writer, ' test_main()' + + def candidate_functions(self): + """functions and methods we will retrieve code objects""" + + mod = self.mod + functions = inspect.getmembers(mod, inspect.isfunction) + functions = [(name, f) for (name, f) in functions if not inspect.isbuiltin(f) and name != "test_main"] + + classes = inspect.getmembers(mod, inspect.isclass) + for classname, cls in classes: + for methodname, method in inspect.getmembers(cls, inspect.ismethod): + if inspect.getmodule(method) == mod: + functions.append(("%s.%s" % (classname, methodname), method)) + return functions + + def extract_code_obj(self, f_or_code): + if inspect.iscode(f_or_code): + code = f_or_code + else: + code = f_or_code.func_code + self.extract_def(code) + + def extract_def(self, code): + if code in self.codeobjs_names: + #print >> sys.stderr, "Already seen", code + return "_codeobjs[%r]" % (self.codeobjs_names[code],) + + co_name = code.co_name + #print >> sys.stderr, "Processing", code + name = co_name + "." + str(self.counters[co_name]) + self.counters[co_name] += 1 + self.codeobjs_names[code] = name + values = [] + self.depend.add_edge(code, ROOT) + for attr in attrs: + # treat co_consts specially - maybe also need to use pickling in case repr is not suitable + if attr == 'co_consts': + co_consts = [] + for const in getattr(code, attr): + if inspect.iscode(const): + #print >> sys.stderr, "Extracting code const " + str(const) + co_consts.append(self.extract_def(const)) + self.depend.add_edge(const, code) + else: + co_consts.append(repr(const)) + values.append((attr, "["+', '.join(co_consts)+"]")) + else: + values.append((attr, repr(getattr(code, attr)))) + self.codeobjs[code] = "PyBytecode(\n" + '\n'.join([' '* 4 + v + ', # ' + attr for (attr, v) in values])+"\n )" + return "_codeobjs[%r]" % (name,) + + +# for now, just use the cwd +def import_modules(path): + import glob + import os.path + + sys.path.insert(0, path) + for name in sorted(glob.iglob("test/test_*.py")): + modname = os.path.splitext(os.path.basename(name))[0] + qualified_name = "test." + modname + print "Trying", qualified_name + try: + topmod = __import__(qualified_name) + except Exception, e: + print "Could not import", qualified_name, ":", repr(e) + continue + mod = getattr(topmod, modname) + try: + mod.test_main + except AttributeError, e: + print "No test_main in", qualified_name + continue + + output_name = "test/" + modname + "_pbc.py" + with open(output_name, "w") as f: + print "Extracting", name, "to", output_name + Extract(mod, f).extract() + +if __name__ == '__main__': + path = modname = sys.argv[1] + import_modules(path) Deleted: trunk/jython/src/org/python/compiler/pbc/Bytecode.java =================================================================== --- branches/pbcvm/src/org/python/compiler/pbc/Bytecode.java 2009-02-24 04:25:13 UTC (rev 6042) +++ trunk/jython/src/org/python/compiler/pbc/Bytecode.java 2009-02-24 05:45:38 UTC (rev 6046) @@ -1,555 +0,0 @@ -package org.python.compiler.pbc; - -// Copyright (c) 2009 Jython Developers -// -// ported from peak.util.assembler (BytecodeAssembler): -// Copyright (C) 1996-2004 by Phillip J. Eby and Tyler C. Sarna. -// All rights reserved. This software may be used under the same terms -// as Zope or Python. (http://cvs.eby-sarna.com/*checkout*/PEAK/README.txt) -// -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.python.core.Py; -import org.python.core.Opcode; -import org.python.core.PyBaseCode; -import org.python.core.PyBytecode; -import org.python.core.PyObject; - -// must be thread confined, as might be expected -class Bytecode { - - private int co_argcount = 0; - private int co_stacksize = 0; - private int co_flags = PyBaseCode.CO_OPTIMIZED | PyBaseCode.CO_NEWLOCALS; // typical usage -// co_filename = '<generated code>' -// co_name = '<lambda>' -// co_firstlineno = 0 -// co_freevars = () -// co_cellvars = () -// _last_lineofs = 0 -// _ss = 0 -// _tmp_level = 0 -// - - public Bytecode(int co_flags) { - this.co_flags = co_flags; - co_const.put(Py.None, 0); - } -// def __init__(self): -// self.co_code = array('B') -// self.co_names = [] -// self.co_varnames = [] -// self.blocks = [] - private final List<Integer> stack_history = new ArrayList<Integer>(); - private final List<Integer> co_code = new ArrayList<Integer>(); - private final List<Integer> co_lnotab = new ArrayList<Integer>(); - private final Map<PyObject, Integer> co_const = new HashMap<PyObject, Integer>(); - - private void emit(int opcode) { - assert (opcode >= 0 && opcode <= 0xFF); // at this point we should verify we are only emitting unsigned bytes - co_code.add(opcode); - } - - private void emit(int opcode, int oparg) { - if (oparg > 0xFFFF) { - emit(Opcode.EXTENDED_ARG); - emit((oparg >> 16) & 0xFF); - emit((oparg >> 24) & 0xFF); - } - emit(opcode); - emit(oparg & 0xFF); - emit((oparg >> 8) & 0xFF); - } - - private void LOAD_CONST(PyObject constant) { - int arg; - if (co_const.containsKey(constant)) { - arg = co_const.get(constant); - } else { - arg = co_const.size() + 1; - co_const.put(constant, arg); - } - stackchange(0, 1); - emit(Opcode.LOAD_CONST, arg); - } - - private void RETURN_VALUE() { - stackchange(1, 0); - emit(Opcode.RETURN_VALUE); - stack_unknown(); - } - - public void code() { -// return new PyBytecode(); - } - - -// - -// -// def locals_written(self): -// vn = self.co_varnames -// hl = dict.fromkeys([STORE_FAST, DELETE_FAST]) -// return dict.fromkeys([vn[arg] for ofs, op, arg in self if op in hl]) -// -// -// -// - public void set_lineno(int lno) { -// if not self.co_firstlineno: -// self.co_firstlineno = self._last_line = lno -// return -// -// append = self.co_lnotab.append -// incr_line = lno - self._last_line -// incr_addr = len(self.co_code) - self._last_lineofs -// if not incr_line: -// return -// -// assert incr_addr>=0 and incr_line>=0 -// -// while incr_addr>255: -// append(255) -// append(0) -// incr_addr -= 255 -// -// while incr_line>255: -// append(incr_addr) -// append(255) -// incr_line -= 255 -// incr_addr = 0 -// -// if incr_addr or incr_line: -// append(incr_addr) -// append(incr_line) -// -// self._last_line = lno -// self._last_lineofs = len(self.co_code) - } - // - - public void YIELD_VALUE() { - stackchange(1, 1); - co_flags |= PyBaseCode.CO_GENERATOR; - emit(Opcode.YIELD_VALUE); - } - - // defaults? def CALL_FUNCTION(self, argc=0, kwargc=0, op=CALL_FUNCTION, extra=0): - public void CALL_FUNCTION(int argc, int kwargc, int op, int extra) { - stackchange(1 + argc + 2 * kwargc + extra, 1); - emit(op); - emit(argc); - emit(kwargc); - } -// -// def CALL_FUNCTION_VAR(self, argc=0, kwargc=0): -// self.CALL_FUNCTION(argc,kwargc,CALL_FUNCTION_VAR, 1) # 1 for *args -// -// def CALL_FUNCTION_KW(self, argc=0, kwargc=0): -// self.CALL_FUNCTION(argc,kwargc,CALL_FUNCTION_KW, 1) # 1 for **kw -// -// def CALL_FUNCTION_VAR_KW(self, argc=0, kwargc=0): -// self.CALL_FUNCTION(argc,kwargc,CALL_FUNCTION_VAR_KW, 2) # 2 *args,**kw -// - - public void BUILD_TUPLE(int count) { - stackchange(count, 1); - emit(Opcode.BUILD_TUPLE, count); - } - - public void BUILD_LIST(int count) { - stackchange(count, 1); - emit(Opcode.BUILD_LIST, count); - } - - public void UNPACK_SEQUENCE(int count) { - stackchange(1, count); - emit(Opcode.UNPACK_SEQUENCE, count); - } - - public void BUILD_SLICE(int count) { - if (count != 2 && count != 3) { - throw Py.AssertionError("Invalid number of arguments for BUILD_SLICE"); - } - stackchange(count, 1); - emit(Opcode.BUILD_SLICE, count); - } - - public void DUP_TOPX(int count) { - stackchange(count, count * 2); - emit(Opcode.DUP_TOPX, count); - } - - public void RAISE_VARARGS(int argc) { - if (0 <= argc && argc <= 3) { - throw Py.AssertionError("Invalid number of arguments for RAISE_VARARGS"); - } - stackchange(argc, 0); - emit(Opcode.RAISE_VARARGS, argc); - } - - public void MAKE_FUNCTION(int ndefaults) { - stackchange(1 + ndefaults, 1); - emit(Opcode.MAKE_FUNCTION, ndefaults); - } - - public void MAKE_CLOSURE(int ndefaults, int freevars) { - freevars = 1; - stackchange(1 + freevars + ndefaults, 1); - emit(Opcode.MAKE_CLOSURE, ndefaults); - } - - public int here() { - return co_code.size(); - } - private int _ss = -1; - - public void set_stack_size(int size) { - if (size < 0) { - throw Py.AssertionError("Stack underflow"); - } - if (size > co_stacksize) { - co_stacksize = size; - } - int bytes = co_code.size() - stack_history.size() + 1; - if (bytes > 0) { - for (int i = 0; i < bytes; i++) { - stack_history.add(_ss); - } - } - _ss = size; - } - - public int get_stack_size() { - return _ss; - } - - public void stackchange(int inputs, int outputs) { - if (_ss == -1) { - throw Py.AssertionError("Unknown stack size at this location"); - } - set_stack_size(get_stack_size() - inputs); // check underflow - set_stack_size(get_stack_size() + outputs); // update maximum height - - } - - public void stack_unknown() { - _ss = -1; - } - - public void branch_stack(int location, int expected) { - if (location >= stack_history.size()) { - if (location > co_code.size()) { - throw Py.AssertionError(String.format( - "Forward-looking stack prediction! %d, %d", location, co_code.size())); - } - int actual = get_stack_size(); - if (actual == -1) { - actual = expected; - set_stack_size(actual); - stack_history.set(location, actual); - } else { - actual = stack_history.get(location); - if (actual == -1) { - actual = expected; - stack_history.set(location, actual); - } - if (actual != expected) { - throw Py.AssertionError(String.format( - "Stack level mismatch: actual=%d expected=%d", actual, expected)); - } - } - } - } - -// def jump(self, op, arg=None): -// def jump_target(offset): -// target = offset -// if op not in hasjabs: -// target = target - (posn+3) -// assert target>=0, "Relative jumps can't go backwards" -// if target>0xFFFF: -// target = offset - (posn+6) -// return target -// -// def backpatch(offset): -// target = jump_target(offset) -// if target>0xFFFF: -// raise AssertionError("Forward jump span must be <64K bytes") -// self.patch_arg(posn, 0, target) -// self.branch_stack(offset, old_level) -// -// if op==FOR_ITER: -// old_level = self.stack_size = self.stack_size - 1 -// self.stack_size += 2 -// else: -// old_level = self.stack_size -// posn = self.here() -// -// if arg is not None: -// self.emit_arg(op, jump_target(arg)) -// self.branch_stack(arg, old_level) -// lbl = None -// else: -// self.emit_arg(op, 0) -// def lbl(code=None): -// backpatch(self.here()) -// if op in (JUMP_FORWARD, JUMP_ABSOLUTE, CONTINUE_LOOP): -// self.stack_unknown() -// return lbl -// -// def COMPARE_OP(self, op): -// self.stackchange((2,1)) -// self.emit_arg(COMPARE_OP, compares[op]) -// -// -// def setup_block(self, op): -// jmp = self.jump(op) -// self.blocks.append((op,self.stack_size,jmp)) -// return jmp -// -// def SETUP_EXCEPT(self): -// ss = self.stack_size -// self.stack_size = ss+3 # simulate the level at "except:" time -// self.setup_block(SETUP_EXCEPT) -// self.stack_size = ss # restore the current level -// -// def SETUP_FINALLY(self): -// ss = self.stack_size -// self.stack_size = ss+3 # allow for exceptions -// self.stack_size = ss+1 # simulate the level after the None is pushed -// self.setup_block(SETUP_FINALLY) -// self.stack_size = ss # restore original level -// -// def SETUP_LOOP(self): -// self.setup_block(SETUP_LOOP) -// -// def POP_BLOCK(self): -// if not self.blocks: -// raise AssertionError("Not currently in a block") -// -// why, level, fwd = self.blocks.pop() -// self.emit(POP_BLOCK) -// -// if why!=SETUP_LOOP: -// if why==SETUP_FINALLY: -// self.LOAD_CONST(None) -// fwd() -// else: -// self.stack_size = level-3 # stack level resets here -// else_ = self.JUMP_FORWARD() -// fwd() -// return else_ -// else: -// return fwd -// -// -// def assert_loop(self): -// for why,level,fwd in self.blocks: -// if why==SETUP_LOOP: -// return -// raise AssertionError("Not inside a loop") -// -// def BREAK_LOOP(self): -// self.assert_loop(); self.emit(BREAK_LOOP) -// self.stack_unknown() -// -// def CONTINUE_LOOP(self, label): -// self.assert_loop() -// if self.blocks[-1][0]==SETUP_LOOP: -// op = JUMP_ABSOLUTE # more efficient if not in a nested block -// else: -// op = CONTINUE_LOOP -// return self.jump(op, label) -// -// def __call__(self, *args): -// last = None -// for ob in args: -// if callable(ob): -// last = ob(self) -// else: -// try: -// f = generate_types[type(ob)] -// except KeyError: -// raise TypeError("Can't generate", ob) -// else: -// last = f(self, ob) -// return last -// -// def return_(self, ob=None): -// return self(ob, Code.RETURN_VALUE) -// -// decorate(classmethod) -// def from_function(cls, function, copy_lineno=False): -// code = cls.from_code(function.func_code, copy_lineno) -// return code -// -// -// decorate(classmethod) -// def from_code(cls, code, copy_lineno=False): -// import inspect -// self = cls.from_spec(code.co_name, *inspect.getargs(code)) -// if copy_lineno: -// self.set_lineno(code.co_firstlineno) -// self.co_filename = code.co_filename -// self.co_freevars = code.co_freevars # XXX untested! -// return self -// -// decorate(classmethod) -// def from_spec(cls, name='<lambda>', args=(), var=None, kw=None): -// self = cls() -// self.co_name = name -// self.co_argcount = len(args) -// self.co_varnames.extend(args) -// if var: -// self.co_varnames.append(var) -// self.co_flags |= CO_VARARGS -// if kw: -// self.co_varnames.append(kw) -// self.co_flags |= CO_VARKEYWORDS -// -// def tuple_arg(args): -// self.UNPACK_SEQUENCE(len(args)) -// for arg in args: -// if not isinstance(arg, basestring): -// tuple_arg(arg) -// else: -// self.STORE_FAST(arg) -// -// for narg, arg in enumerate(args): -// if not isinstance(arg, basestring): -// dummy_name = '.'+str(narg) -// self.co_varnames[narg] = dummy_name -// self.LOAD_FAST(dummy_name) -// tuple_arg(arg) -// -// return self -// -// -// def patch_arg(self, offset, oldarg, newarg): -// code = self.co_code -// if (oldarg>0xFFFF) != (newarg>0xFFFF): -// raise AssertionError("Can't change argument size", oldarg, newarg) -// code[offset+1] = newarg & 255 -// code[offset+2] = (newarg>>8) & 255 -// if newarg>0xFFFF: -// newarg >>=16 -// code[offset-2] = newarg & 255 -// code[offset-1] = (newarg>>8) & 255 -// -// def nested(self, name='<lambda>', args=(), var=None, kw=None, cls=None): -// if cls is None: -// cls = Code -// code = cls.from_spec(name, args, var, kw) -// code.co_filename=self.co_filename -// return code -// -// def __iter__(self): -// i = 0 -// extended_arg = 0 -// code = self.co_code -// n = len(code) -// while i < n: -// op = code[i] -// if op >= HAVE_ARGUMENT: -// oparg = code[i+1] + code[i+2]*256 + extended_arg -// extended_arg = 0 -// if op == EXTENDED_ARG: -// extended_arg = oparg*65536 -// i+=3 -// continue -// yield i, op, oparg -// i += 3 -// else: -// yield i, op, None -// i += 1 -// -// -// -// -// def makefree(self, names): -// nowfree = dict.fromkeys(self.co_freevars) -// newfree = [n for n in names if n not in nowfree] -// if newfree: -// self.co_freevars += tuple(newfree) -// self._locals_to_cells() -// -// def makecells(self, names): -// nowcells = dict.fromkeys(self.co_cellvars+self.co_freevars) -// newcells = [n for n in names if n not in nowcells] -// if new... [truncated message content] |
From: <fwi...@us...> - 2009-02-24 20:42:30
|
Revision: 6047 http://jython.svn.sourceforge.net/jython/?rev=6047&view=rev Author: fwierzbicki Date: 2009-02-24 20:42:25 +0000 (Tue, 24 Feb 2009) Log Message: ----------- Added a target and infrastructure for compiling the ctypes_test.c needed for test__rawffi.py. So far only tested on OS X. Used cpptasks from http://ant-contrib.sourceforge.net/cpptasks/index.html Modified Paths: -------------- trunk/jython/build.xml Added Paths: ----------- trunk/jython/extlibs/cpptasks/ trunk/jython/extlibs/cpptasks/cpptasks.jar Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-02-24 05:45:38 UTC (rev 6046) +++ trunk/jython/build.xml 2009-02-24 20:42:25 UTC (rev 6047) @@ -168,6 +168,7 @@ <pathelement path="${extlibs.dir}/junit-3.8.2.jar" /> <pathelement path="${exposed.dir}" /> <pathelement path="${compile.dir}" /> + <pathelement path="${cpptasks.jar.dir}" /> </path> <!-- 64 bit Java 6 needs roughly 96m for regrtest on most platforms, but Apple's needs more --> @@ -215,6 +216,7 @@ <property file="${basedir}/ant.properties" /> <property name="svnant.jar.dir" value="${basedir}/extlibs/svnant-jars" /> + <property name="cpptasks.jar.dir" value="${basedir}/extlibs/cpptasks/cpptasks.jar" /> <!-- use this property to distinguish a full-build from a developer-build --> <property name="full-build" value="true" /> @@ -493,8 +495,6 @@ nowarn="${nowarn}"> <classpath refid="test.classpath" /> </javac> - - <copy file="${source.dir}/org/python/modules/ucnhash.dat" todir="${compile.dir}/org/python/modules" preservelastmodified="true" /> @@ -506,6 +506,23 @@ </copy> </target> + <!-- + If you run this before running regrtest, test__rawffi.py should pass. + So far I have been unable to enable cpptasks without passing an arg to ant. + To run this task like I am do: + + ant -lib extlibs/cpptasks/cpptasks.jar compile_cpp + + XXX: get cpptasks running without an arg to ant. + --> + <target name="compile_cpp" depends="compile"> + <taskdef resource="cpptasks.tasks"/> + <cc outtype="shared" subsystem="console" outfile="ctypes_test" objdir="${compile.dir}"> + <fileset dir="tests/c" includes="*.c"/> + </cc> + </target> + + <target name="expose" depends="init"> <taskdef name="expose" classname="org.python.expose.generate.ExposeTask"> <classpath> Added: trunk/jython/extlibs/cpptasks/cpptasks.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/extlibs/cpptasks/cpptasks.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-03-01 20:42:55
|
Revision: 6049 http://jython.svn.sourceforge.net/jython/?rev=6049&view=rev Author: fwierzbicki Date: 2009-03-01 20:42:46 +0000 (Sun, 01 Mar 2009) Log Message: ----------- Update to antlr 3.1.2. This required deleting mismatch() override in Python.g and PythonPartial.g. Modified Paths: -------------- trunk/jython/build.xml trunk/jython/grammar/Python.g trunk/jython/grammar/PythonPartial.g Added Paths: ----------- trunk/jython/extlibs/antlr-3.1.2.jar trunk/jython/extlibs/antlr-runtime-3.1.2.jar Removed Paths: ------------- trunk/jython/extlibs/antlr-3.1.1-runtime.jar trunk/jython/extlibs/antlr-3.1.1.jar Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-02-24 22:39:22 UTC (rev 6048) +++ trunk/jython/build.xml 2009-03-01 20:42:46 UTC (rev 6049) @@ -151,7 +151,7 @@ <pathelement path="${extlibs.dir}/mysql-connector-java-5.1.6.jar" /> <pathelement path="${extlibs.dir}/postgresql-8.3-603.jdbc4.jar" /> <pathelement path="${extlibs.dir}/antlr-2.7.7.jar" /> - <pathelement path="${extlibs.dir}/antlr-3.1.1.jar" /> + <pathelement path="${extlibs.dir}/antlr-3.1.2.jar" /> <pathelement path="${extlibs.dir}/stringtemplate-3.2.jar" /> <pathelement path="${extlibs.dir}/asm-3.1.jar" /> @@ -539,7 +539,7 @@ <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="extlibs/jarjar-0.7.jar"/> <jarjar destfile="${dist.dir}/${jython.deploy.jar}"> <zipfileset src="${dist.dir}/${jython.dev.jar}"/> - <zipfileset src="extlibs/antlr-3.1.1-runtime.jar"/> + <zipfileset src="extlibs/antlr-3.1.2-runtime.jar"/> <rule pattern="org.antlr.runtime.**" result="org.python.antlr.runtime.@1"/> <zipfileset src="extlibs/asm-3.1.jar"/> <zipfileset src="extlibs/asm-commons-3.1.jar"/> Deleted: trunk/jython/extlibs/antlr-3.1.1-runtime.jar =================================================================== (Binary files differ) Deleted: trunk/jython/extlibs/antlr-3.1.1.jar =================================================================== (Binary files differ) Added: trunk/jython/extlibs/antlr-3.1.2.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/extlibs/antlr-3.1.2.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/jython/extlibs/antlr-runtime-3.1.2.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/extlibs/antlr-runtime-3.1.2.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/jython/grammar/Python.g =================================================================== --- trunk/jython/grammar/Python.g 2009-02-24 22:39:22 UTC (rev 6048) +++ trunk/jython/grammar/Python.g 2009-03-01 20:42:46 UTC (rev 6049) @@ -170,12 +170,6 @@ actions.setErrorHandler(eh); } - protected void mismatch(IntStream input, int ttype, BitSet follow) throws RecognitionException { - if (errorHandler.mismatch(this, input, ttype, follow)) { - super.mismatch(input, ttype, follow); - } - } - protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException { Modified: trunk/jython/grammar/PythonPartial.g =================================================================== --- trunk/jython/grammar/PythonPartial.g 2009-02-24 22:39:22 UTC (rev 6048) +++ trunk/jython/grammar/PythonPartial.g 2009-03-01 20:42:46 UTC (rev 6049) @@ -75,12 +75,6 @@ @members { private ErrorHandler errorHandler = new FailFastHandler(); - protected void mismatch(IntStream input, int ttype, BitSet follow) throws RecognitionException { - if (errorHandler.mismatch(this, input, ttype, follow)) { - super.mismatch(input, ttype, follow); - } - } - protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-03-03 15:54:10
|
Revision: 6064 http://jython.svn.sourceforge.net/jython/?rev=6064&view=rev Author: fwierzbicki Date: 2009-03-03 15:54:04 +0000 (Tue, 03 Mar 2009) Log Message: ----------- Test and fix for http://bugs.jython.org/issue1222877. Duplicate keyword args where erroneously permitted in Jython. Thanks to Khalid Zuberi for taking a crack at a patch, I modified the patch to avoid an extra loop. Modified Paths: -------------- trunk/jython/Lib/test/test_func_syntax_jy.py trunk/jython/src/org/python/core/ArgParser.java Modified: trunk/jython/Lib/test/test_func_syntax_jy.py =================================================================== --- trunk/jython/Lib/test/test_func_syntax_jy.py 2009-03-03 07:09:37 UTC (rev 6063) +++ trunk/jython/Lib/test/test_func_syntax_jy.py 2009-03-03 15:54:04 UTC (rev 6064) @@ -9,6 +9,10 @@ self.assertRaises(SyntaxError, eval, "parrot(voltage=.5, \'dead\')") + def test_dup_keywords(self): + self.assertRaises(TypeError, eval, + "complex(imag=4, imag=2)") + def test_main(): test.test_support.run_unittest(FuncSyntaxTest) Modified: trunk/jython/src/org/python/core/ArgParser.java =================================================================== --- trunk/jython/src/org/python/core/ArgParser.java 2009-03-03 07:09:37 UTC (rev 6063) +++ trunk/jython/src/org/python/core/ArgParser.java 2009-03-03 15:54:04 UTC (rev 6064) @@ -1,5 +1,8 @@ package org.python.core; +import java.util.HashSet; +import java.util.Set; + /** * A utility class for handling mixed positional and keyword arguments. * @@ -239,19 +242,26 @@ } private void check() { - int nargs = this.args.length - this.kws.length; - l1: for (int i = 0; i < this.kws.length; i++) { - for (int j = 0; j < this.params.length; j++) { - if (this.kws[i].equals(this.params[j])) { + Set<Integer> usedKws = new HashSet<Integer>(); + int nargs = args.length - kws.length; + l1: for (int i = 0; i < kws.length; i++) { + for (int j = 0; j < params.length; j++) { + if (kws[i].equals(params[j])) { if (j < nargs) { throw Py.TypeError("keyword parameter '" - + this.params[j] + + params[j] + "' was given by position and by name"); } + if (usedKws.contains(j)) { + throw Py.TypeError(String.format( + "%s got multiple values for keyword argument '%s'", + funcname, params[j])); + } + usedKws.add(j); continue l1; } } - throw Py.TypeError("'" + this.kws[i] + "' is an invalid keyword " + throw Py.TypeError("'" + kws[i] + "' is an invalid keyword " + "argument for this function"); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-03-06 04:15:56
|
Revision: 6071 http://jython.svn.sourceforge.net/jython/?rev=6071&view=rev Author: fwierzbicki Date: 2009-03-06 04:15:54 +0000 (Fri, 06 Mar 2009) Log Message: ----------- Added mtime to the compiled Jython classes to match CPython behavior. Fixes: http://bugs.jython.org/issue1567212 and http://bugs.jython.org/issue1024 Modified Paths: -------------- trunk/jython/src/org/python/compiler/ClassFile.java trunk/jython/src/org/python/compiler/Module.java trunk/jython/src/org/python/core/imp.java trunk/jython/src/org/python/modules/imp.java Added Paths: ----------- trunk/jython/Lib/test/test_compile_jy.py trunk/jython/src/org/python/compiler/MTime.java trunk/jython/src/org/python/core/AnnotationReader.java Removed Paths: ------------- trunk/jython/src/org/python/core/APIReader.java Added: trunk/jython/Lib/test/test_compile_jy.py =================================================================== --- trunk/jython/Lib/test/test_compile_jy.py (rev 0) +++ trunk/jython/Lib/test/test_compile_jy.py 2009-03-06 04:15:54 UTC (rev 6071) @@ -0,0 +1,57 @@ +import unittest +import os +import sys +import shutil +import __builtin__ +import py_compile +from test.test_support import run_unittest, TESTFN, is_jython + +class TestMtime(unittest.TestCase): + + def test_mtime_compile(self): + """ + This test exercises the mtime annotation that is now stored in Jython + compiled files. CPython already stores an mtime in its pyc files. To + exercise this functionality, I am writing a py file, compiling it, + setting the os modified time to a very low value on the compiled file, + then changing the py file after a small sleep. On CPython, this would + still cause a re-compile. In Jython before this fix it would not. + See http://bugs.jython.org/issue1024 + """ + + import time + os.mkdir(TESTFN) + try: + mod = "mod1" + source_path = os.path.join(TESTFN, "%s.py" % mod) + if is_jython: + compiled_path = os.path.join(TESTFN, "%s$py.class" % mod) + else: + compiled_path = os.path.join(TESTFN, "%s.pyc" % mod) + fp = open(source_path, "w") + fp.write("def foo(): return 'first'\n") + fp.close() + py_compile.compile(source_path) + + #sleep so that the internal mtime is older for the next source write. + time.sleep(1) + + fp = open(source_path, "w") + fp.write("def foo(): return 'second'\n") + fp.close() + + # make sure the source file's mtime is artificially younger than + # the compiled path's mtime. + os.utime(source_path, (1,1)) + + sys.path.append(TESTFN) + import mod1 + self.assertEquals(mod1.foo(), 'second') + finally: + shutil.rmtree(TESTFN) + +def test_main(): + run_unittest(TestMtime) + +if __name__ == "__main__": + test_main() Modified: trunk/jython/src/org/python/compiler/ClassFile.java =================================================================== --- trunk/jython/src/org/python/compiler/ClassFile.java 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/src/org/python/compiler/ClassFile.java 2009-03-06 04:15:54 UTC (rev 6071) @@ -19,6 +19,7 @@ { ClassWriter cw; int access; + long mtime; public String name; String superclass; String sfilename; @@ -37,14 +38,19 @@ } public ClassFile(String name) { - this(name, "java/lang/Object", Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_PUBLIC); + this(name, "java/lang/Object", Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_PUBLIC, + org.python.core.imp.NO_MTIME); } 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()); @@ -103,6 +109,10 @@ av.visit("value", new Integer(org.python.core.imp.APIVersion)); av.visitEnd(); + av = cw.visitAnnotation("Lorg/python/compiler/MTime;", true); + av.visit("value", new Long(mtime)); + av.visitEnd(); + if (sfilename != null) { cw.visitSource(sfilename, null); } Added: trunk/jython/src/org/python/compiler/MTime.java =================================================================== --- trunk/jython/src/org/python/compiler/MTime.java (rev 0) +++ trunk/jython/src/org/python/compiler/MTime.java 2009-03-06 04:15:54 UTC (rev 6071) @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2008 Jython Developers + * Licensed to PSF under a Contributor Agreement. + */ +package org.python.compiler; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface MTime { + long value(); +} Modified: trunk/jython/src/org/python/compiler/Module.java =================================================================== --- trunk/jython/src/org/python/compiler/Module.java 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/src/org/python/compiler/Module.java 2009-03-06 04:15:54 UTC (rev 6071) @@ -296,11 +296,17 @@ public boolean linenumbers; Future futures; Hashtable scopes; + long mtime; public Module(String name, String filename, boolean linenumbers) { + this(name, filename, linenumbers, org.python.core.imp.NO_MTIME); + } + + public Module(String name, String filename, boolean linenumbers, long mtime) { this.linenumbers = linenumbers; + this.mtime = mtime; classfile = new ClassFile(name, "org/python/core/PyFunctionTable", - ACC_SYNCHRONIZED | ACC_PUBLIC); + ACC_SYNCHRONIZED | ACC_PUBLIC, mtime); constants = new Hashtable(); sfilename = filename; if (filename != null) @@ -313,7 +319,7 @@ } public Module(String name) { - this(name, name+".py", true); + this(name, name+".py", true, org.python.core.imp.NO_MTIME); } // This block of code handles the pool of Python Constants @@ -633,14 +639,22 @@ } throw new ParseException(msg,node); } + public static void compile(mod node, OutputStream ostream, + String name, String filename, + boolean linenumbers, boolean printResults, + CompilerFlags cflags) + throws Exception + { + compile(node, ostream, name, filename, linenumbers, printResults, cflags, org.python.core.imp.NO_MTIME); + } public static void compile(mod node, OutputStream ostream, String name, String filename, boolean linenumbers, boolean printResults, - CompilerFlags cflags) + CompilerFlags cflags, long mtime) throws Exception { - Module module = new Module(name, filename, linenumbers); + Module module = new Module(name, filename, linenumbers, mtime); if (cflags == null) { cflags = new CompilerFlags(); } Deleted: trunk/jython/src/org/python/core/APIReader.java =================================================================== --- trunk/jython/src/org/python/core/APIReader.java 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/src/org/python/core/APIReader.java 2009-03-06 04:15:54 UTC (rev 6071) @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2008 Jython Developers - * Licensed to PSF under a Contributor Agreement. - */ -package org.python.core; - -import java.io.IOException; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.commons.EmptyVisitor; - -/** - * This class reads a classfile from a byte array and pulls out the value of the class annotation - * for APIVersion, which can then be retrieved by a call to getVersion(). - * - * Hopefully the use of ClassReader in this implementation is not too expensive. I suspect it is not - * since EmptyVisitor is just a bag of empty methods so shouldn't cost too much. If it turns out to - * cost too much, we will want to implement a special purpose ClassReader that only reads out the - * APIVersion annotation I think. - */ -public class APIReader extends EmptyVisitor { - - private boolean nextVisitIsVersion = false; - - private int version = -1; - - /** - * Reads the classfile bytecode in data and to extract the version. - * @throws IOException - if the classfile is malformed. - */ - public APIReader(byte[] data) throws IOException { - ClassReader r; - try { - r = new ClassReader(data); - } catch (ArrayIndexOutOfBoundsException e) { - IOException ioe = new IOException("Malformed bytecode: not enough data"); - ioe.initCause(e);// IOException didn't grow a constructor that could take a cause till - // 1.6, so do it the old fashioned way - throw ioe; - } - r.accept(this, 0); - } - - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - nextVisitIsVersion = desc.equals("Lorg/python/compiler/APIVersion;"); - return this; - } - - public void visit(String name, Object value) { - if (nextVisitIsVersion) { - version = (Integer)value; - nextVisitIsVersion = false; - } - } - - public int getVersion() { - return version; - } -} Copied: trunk/jython/src/org/python/core/AnnotationReader.java (from rev 6064, trunk/jython/src/org/python/core/APIReader.java) =================================================================== --- trunk/jython/src/org/python/core/AnnotationReader.java (rev 0) +++ trunk/jython/src/org/python/core/AnnotationReader.java 2009-03-06 04:15:54 UTC (rev 6071) @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2008 Jython Developers + * Licensed to PSF under a Contributor Agreement. + */ +package org.python.core; + +import java.io.IOException; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.commons.EmptyVisitor; + +/** + * This class reads a classfile from a byte array and pulls out the value of the class annotation + * for APIVersion, which can then be retrieved by a call to getVersion(). + * + * Hopefully the use of ClassReader in this implementation is not too expensive. I suspect it is not + * since EmptyVisitor is just a bag of empty methods so shouldn't cost too much. If it turns out to + * cost too much, we will want to implement a special purpose ClassReader that only reads out the + * APIVersion annotation I think. + */ +public class AnnotationReader extends EmptyVisitor { + + private boolean nextVisitIsVersion = false; + private boolean nextVisitIsMTime = false; + + private int version = -1; + private long mtime = -1; + + /** + * Reads the classfile bytecode in data and to extract the version. + * @throws IOException - if the classfile is malformed. + */ + public AnnotationReader(byte[] data) throws IOException { + ClassReader r; + try { + r = new ClassReader(data); + } catch (ArrayIndexOutOfBoundsException e) { + IOException ioe = new IOException("Malformed bytecode: not enough data"); + ioe.initCause(e);// IOException didn't grow a constructor that could take a cause till + // 1.6, so do it the old fashioned way + throw ioe; + } + r.accept(this, 0); + } + + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + nextVisitIsVersion = desc.equals("Lorg/python/compiler/APIVersion;"); + nextVisitIsMTime = desc.equals("Lorg/python/compiler/MTime;"); + return this; + } + + public void visit(String name, Object value) { + if (nextVisitIsVersion) { + version = (Integer)value; + nextVisitIsVersion = false; + } else if (nextVisitIsMTime) { + mtime = (Long)value; + nextVisitIsVersion = false; + } + } + + public int getVersion() { + return version; + } + + public long getMTime() { + return mtime; + } +} Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/src/org/python/core/imp.java 2009-03-06 04:15:54 UTC (rev 6071) @@ -22,6 +22,8 @@ public static final int APIVersion = 17; + public static final int NO_MTIME = -1; + // This should change to 0 for Python 2.7 and 3.0 see PEP 328 public static final int DEFAULT_LEVEL = -1; @@ -85,12 +87,17 @@ throw Py.IOError(ioe); } } + static PyObject createFromPyClass(String name, InputStream fp, boolean testing, + String sourceName, String compiledName) { + return createFromPyClass(name, fp, testing, sourceName, compiledName, NO_MTIME); + } + static PyObject createFromPyClass(String name, InputStream fp, boolean testing, - String sourceName, String compiledName) { + String sourceName, String compiledName, long mtime) { byte[] data = null; try { - data = readCode(name, fp, testing); + data = readCode(name, fp, testing, mtime); } catch (IOException ioe) { if (!testing) { throw Py.ImportError(ioe.getMessage() + "[name=" + name + ", source=" + sourceName @@ -118,9 +125,13 @@ } public static byte[] readCode(String name, InputStream fp, boolean testing) throws IOException { + return readCode(name, fp, testing, NO_MTIME); + } + + public static byte[] readCode(String name, InputStream fp, boolean testing, long mtime) throws IOException { byte[] data = readBytes(fp); int api; - APIReader ar = new APIReader(data); + AnnotationReader ar = new AnnotationReader(data); api = ar.getVersion(); if (api != APIVersion) { if (testing) { @@ -130,6 +141,12 @@ + APIVersion + ") in: " + name); } } + if (testing && mtime != NO_MTIME) { + long time = ar.getMTime(); + if (mtime != time) { + return null; + } + } return data; } @@ -146,7 +163,8 @@ if (sourceFilename == null) { sourceFilename = file.toString(); } - return compileSource(name, makeStream(file), sourceFilename); + long mtime = file.lastModified(); + return compileSource(name, makeStream(file), sourceFilename, mtime); } public static String makeCompiledFilename(String filename) { @@ -199,6 +217,10 @@ } public static byte[] compileSource(String name, InputStream fp, String filename) { + return compileSource(name, fp, filename, NO_MTIME); + } + + public static byte[] compileSource(String name, InputStream fp, String filename, long mtime) { ByteArrayOutputStream ofp = new ByteArrayOutputStream(); try { if(filename == null) { @@ -210,7 +232,7 @@ } finally { fp.close(); } - Module.compile(node, ofp, name + "$py", filename, true, false, null); + Module.compile(node, ofp, name + "$py", filename, true, false, null, mtime); return ofp.toByteArray(); } catch(Throwable t) { throw ParserFacade.fixParseError(null, t, filename); @@ -218,12 +240,17 @@ } public static PyObject createFromSource(String name, InputStream fp, String filename) { - return createFromSource(name, fp, filename, null); + return createFromSource(name, fp, filename, null, NO_MTIME); } public static PyObject createFromSource(String name, InputStream fp, String filename, String outFilename) { - byte[] bytes = compileSource(name, fp, filename); + return createFromSource(name, fp, filename, outFilename, NO_MTIME); + } + + public static PyObject createFromSource(String name, InputStream fp, + String filename, String outFilename, long mtime) { + byte[] bytes = compileSource(name, fp, filename, mtime); outFilename = cacheCompiledSource(filename, outFilename, bytes); Py.writeComment(IMPORT_LOG, "'" + name + "' as " + filename); @@ -433,20 +460,20 @@ } if (sourceFile.isFile() && caseok(sourceFile, sourceName)) { + long pyTime = sourceFile.lastModified(); if (compiledFile.isFile() && caseok(compiledFile, compiledName)) { Py.writeDebug(IMPORT_LOG, "trying precompiled " + compiledFile.getPath()); - long pyTime = sourceFile.lastModified(); long classTime = compiledFile.lastModified(); if (classTime >= pyTime) { PyObject ret = createFromPyClass(modName, makeStream(compiledFile), true, - displaySourceName, displayCompiledName); + displaySourceName, displayCompiledName, pyTime); if (ret != null) { return ret; } } } return createFromSource(modName, makeStream(sourceFile), displaySourceName, - compiledFile.getPath()); + compiledFile.getPath(), pyTime); } // If no source, try loading precompiled Modified: trunk/jython/src/org/python/modules/imp.java =================================================================== --- trunk/jython/src/org/python/modules/imp.java 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/src/org/python/modules/imp.java 2009-03-06 04:15:54 UTC (rev 6071) @@ -207,10 +207,18 @@ } else if (name.equals("__init__")) { name = new File(sys.getCurrentWorkingDir()).getName(); } + + File fp = new File(resolvedFilename); + long mtime = -1; + if (fp.isFile()) { + mtime = fp.lastModified(); + } + mod = org.python.core.imp.createFromSource(name.intern(), (InputStream)o, filename.toString(), - compiledName); + compiledName, + mtime); break; case PY_COMPILED: compiledName = filename.toString(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-03-06 18:27:27
|
Revision: 6075 http://jython.svn.sourceforge.net/jython/?rev=6075&view=rev Author: fwierzbicki Date: 2009-03-06 18:27:15 +0000 (Fri, 06 Mar 2009) Log Message: ----------- Merged revisions 5751,6066-6070 via svnmerge from https://jython.svn.sourceforge.net/svnroot/jython/branches/modjy Merging Alan Kennedy's amazing modjy project http://modjy.xhaus.com/ into core of Jython Cut the branch comments down to the interesting ones. Thanks Alan! ........ r6068 | amak | 2009-03-05 10:43:01 -0500 (Thu, 05 Mar 2009) | 1 line Modification to the ModjyJServlet to reflect that it is now part of the jython distribution, rather than a standalone product. ........ r6069 | amak | 2009-03-05 10:54:43 -0500 (Thu, 05 Mar 2009) | 3 lines Adding the original modjy demo application to the Demo subdirectory. This application gives the users a complete running application that they can use as a template for aplication development. In the future, we might develop a more sophisticated application. ........ r6070 | amak | 2009-03-05 17:07:35 -0500 (Thu, 05 Mar 2009) | 1 line Committing the unit tests. There is a readme.txt file in the directory which explains how to run the tests, which depend on mockrunner. ........ Added Paths: ----------- trunk/jython/Demo/modjy_webapp/ trunk/jython/Demo/modjy_webapp/WEB-INF/ trunk/jython/Demo/modjy_webapp/WEB-INF/lib/ trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/ trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt trunk/jython/Demo/modjy_webapp/WEB-INF/web.xml trunk/jython/Demo/modjy_webapp/demo_app.py trunk/jython/Demo/modjy_webapp/readme.txt trunk/jython/Lib/modjy/ trunk/jython/Lib/modjy/__init__.py trunk/jython/Lib/modjy/modjy.py trunk/jython/Lib/modjy/modjy_exceptions.py trunk/jython/Lib/modjy/modjy_impl.py trunk/jython/Lib/modjy/modjy_log.py trunk/jython/Lib/modjy/modjy_params.py trunk/jython/Lib/modjy/modjy_publish.py trunk/jython/Lib/modjy/modjy_response.py trunk/jython/Lib/modjy/modjy_write.py trunk/jython/Lib/modjy/modjy_wsgi.py trunk/jython/src/com/xhaus/ trunk/jython/src/com/xhaus/modjy/ trunk/jython/src/com/xhaus/modjy/ModjyJServlet.java trunk/jython/tests/modjy/ trunk/jython/tests/modjy/__init__.py trunk/jython/tests/modjy/build.xml trunk/jython/tests/modjy/empty.txt trunk/jython/tests/modjy/java/ trunk/jython/tests/modjy/java/com/ trunk/jython/tests/modjy/java/com/xhaus/ trunk/jython/tests/modjy/java/com/xhaus/modjy/ trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestAppInvocation.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestBase.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestContentHeaders.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestEnviron.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestHeaders.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestReturnIterable.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestWSGIStreams.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestWebInf.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestWriteCallable.java trunk/jython/tests/modjy/lib_python_folder/ trunk/jython/tests/modjy/lib_python_folder/__init__.py trunk/jython/tests/modjy/lib_python_folder/add_zips.pth trunk/jython/tests/modjy/lib_python_folder/do_import.pth trunk/jython/tests/modjy/lib_python_folder/mock_framework/ trunk/jython/tests/modjy/lib_python_folder/mock_framework/__init__.py trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/ trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/__init__.py trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/handlers/ trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/handlers/__init__.py trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/handlers/wsgi_handlers.py trunk/jython/tests/modjy/lib_python_folder/script_name_path_info.py trunk/jython/tests/modjy/lib_python_folder/test_lib/ trunk/jython/tests/modjy/lib_python_folder/test_lib/__init__.py trunk/jython/tests/modjy/lib_python_folder/test_lib/some_libs.py trunk/jython/tests/modjy/lib_python_folder/test_modules.zip trunk/jython/tests/modjy/lines.txt trunk/jython/tests/modjy/readme.txt trunk/jython/tests/modjy/test_apps_dir/ trunk/jython/tests/modjy/test_apps_dir/__init__.py trunk/jython/tests/modjy/test_apps_dir/content_header_tests.py trunk/jython/tests/modjy/test_apps_dir/environ_tests.py trunk/jython/tests/modjy/test_apps_dir/header_tests.py trunk/jython/tests/modjy/test_apps_dir/return_tests.py trunk/jython/tests/modjy/test_apps_dir/simple_app.py trunk/jython/tests/modjy/test_apps_dir/stream_tests.py trunk/jython/tests/modjy/test_apps_dir/web_inf_tests.py Removed Paths: ------------- trunk/jython/Demo/modjy_webapp/WEB-INF/ trunk/jython/Demo/modjy_webapp/WEB-INF/lib/ trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/ trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt trunk/jython/Demo/modjy_webapp/WEB-INF/web.xml trunk/jython/Demo/modjy_webapp/demo_app.py trunk/jython/Demo/modjy_webapp/readme.txt trunk/jython/Lib/modjy/__init__.py trunk/jython/Lib/modjy/modjy.py trunk/jython/Lib/modjy/modjy_exceptions.py trunk/jython/Lib/modjy/modjy_impl.py trunk/jython/Lib/modjy/modjy_log.py trunk/jython/Lib/modjy/modjy_params.py trunk/jython/Lib/modjy/modjy_publish.py trunk/jython/Lib/modjy/modjy_response.py trunk/jython/Lib/modjy/modjy_write.py trunk/jython/Lib/modjy/modjy_wsgi.py trunk/jython/src/com/xhaus/modjy/ trunk/jython/src/com/xhaus/modjy/ModjyJServlet.java trunk/jython/tests/modjy/__init__.py trunk/jython/tests/modjy/build.xml trunk/jython/tests/modjy/empty.txt trunk/jython/tests/modjy/java/ trunk/jython/tests/modjy/java/com/ trunk/jython/tests/modjy/java/com/xhaus/ trunk/jython/tests/modjy/java/com/xhaus/modjy/ trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestAppInvocation.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestBase.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestContentHeaders.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestEnviron.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestHeaders.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestReturnIterable.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestWSGIStreams.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestWebInf.java trunk/jython/tests/modjy/java/com/xhaus/modjy/ModjyTestWriteCallable.java trunk/jython/tests/modjy/lib_python_folder/ trunk/jython/tests/modjy/lib_python_folder/__init__.py trunk/jython/tests/modjy/lib_python_folder/add_zips.pth trunk/jython/tests/modjy/lib_python_folder/do_import.pth trunk/jython/tests/modjy/lib_python_folder/mock_framework/ trunk/jython/tests/modjy/lib_python_folder/mock_framework/__init__.py trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/ trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/__init__.py trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/handlers/ trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/handlers/__init__.py trunk/jython/tests/modjy/lib_python_folder/mock_framework/web/handlers/wsgi_handlers.py trunk/jython/tests/modjy/lib_python_folder/script_name_path_info.py trunk/jython/tests/modjy/lib_python_folder/test_lib/ trunk/jython/tests/modjy/lib_python_folder/test_lib/__init__.py trunk/jython/tests/modjy/lib_python_folder/test_lib/some_libs.py trunk/jython/tests/modjy/lib_python_folder/test_modules.zip trunk/jython/tests/modjy/lines.txt trunk/jython/tests/modjy/readme.txt trunk/jython/tests/modjy/test_apps_dir/ trunk/jython/tests/modjy/test_apps_dir/__init__.py trunk/jython/tests/modjy/test_apps_dir/content_header_tests.py trunk/jython/tests/modjy/test_apps_dir/environ_tests.py trunk/jython/tests/modjy/test_apps_dir/header_tests.py trunk/jython/tests/modjy/test_apps_dir/return_tests.py trunk/jython/tests/modjy/test_apps_dir/simple_app.py trunk/jython/tests/modjy/test_apps_dir/stream_tests.py trunk/jython/tests/modjy/test_apps_dir/web_inf_tests.py Property Changed: ---------------- trunk/jython/ Property changes on: trunk/jython ___________________________________________________________________ Modified: svnmerge-integrated - /branches/modjy:1-5750 /branches/pbcvm:1-6045 + /branches/modjy:1-6074 /branches/pbcvm:1-6045 Deleted: trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt =================================================================== --- branches/modjy/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,11 +0,0 @@ -The WEB-INF/lib-python directory, if it exists, is automatically added -to sys.path. Adding jython modules into this directory will make them -available for import into your application. - -If you add your modules in a subdirectory, then be sure that that -subdirectory contains an __init__.py file, so that the subdirectory -is considered to be a package. - -See here for more details. -http://www.rexx.com/~dkuhlman/python_101/python_101.html#SECTION004540000000000000000 -http://www.python.org/doc/essays/packages.html Copied: trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt (from rev 6070, branches/modjy/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt) =================================================================== --- trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt (rev 0) +++ trunk/jython/Demo/modjy_webapp/WEB-INF/lib-python/readme.txt 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,11 @@ +The WEB-INF/lib-python directory, if it exists, is automatically added +to sys.path. Adding jython modules into this directory will make them +available for import into your application. + +If you add your modules in a subdirectory, then be sure that that +subdirectory contains an __init__.py file, so that the subdirectory +is considered to be a package. + +See here for more details. +http://www.rexx.com/~dkuhlman/python_101/python_101.html#SECTION004540000000000000000 +http://www.python.org/doc/essays/packages.html Deleted: trunk/jython/Demo/modjy_webapp/WEB-INF/web.xml =================================================================== --- branches/modjy/Demo/modjy_webapp/WEB-INF/web.xml 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Demo/modjy_webapp/WEB-INF/web.xml 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!DOCTYPE web-app - PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" - "http://java.sun.com/dtd/web-app_2_3.dtd"> -<web-app> - - <display-name>modjy demo application</display-name> - <description> - modjy WSGI demo application - </description> - - <servlet> - <servlet-name>modjy</servlet-name> - <servlet-class>com.xhaus.modjy.ModjyJServlet</servlet-class> - <init-param> - <param-name>python.home</param-name> - <param-value>C:/jython2.5</param-value> - </init-param> -<!-- - There are two different ways you can specify an application to modjy - 1. Using the app_import_name mechanism - 2. Using a combination of app_directory/app_filename/app_callable_name - Examples of both are given below - See the documenation for more details. - http://modjy.xhaus.com/locating.html#locating_callables ---> -<!-- - This is the app_import_name mechanism. If you specify a value - for this variable, then it will take precedence over the other mechanism - <init-param> - <param-name>app_import_name</param-name> - <param-value>my_wsgi_module.my_handler_class().handler_method</param-value> - </init-param> ---> -<!-- - And this is the app_directory/app_filename/app_callable_name combo - The defaults for these three variables are ""/application.py/handler - So if you specify no values at all for any of app_* variables, then modjy - will by default look for "handler" in "application.py" in the servlet - context root. - <init-param> - <param-name>app_directory</param-name> - <param-value>some_sub_directory</param-value> - </init-param> ---> - <init-param> - <param-name>app_filename</param-name> - <param-value>demo_app.py</param-value> - </init-param> -<!-- - Supply a value for this parameter if you want your application - callable to have a different name than the default. - <init-param> - <param-name>app_callable_name</param-name> - <param-value>my_handler_func</param-value> - </init-param> ---> - <!-- Do you want application callables to be cached? --> - <init-param> - <param-name>cache_callables</param-name> - <param-value>1</param-value> - </init-param> - <!-- Should the application be reloaded if it's .py file changes? --> - <!-- Does not work with the app_import_name mechanism --> - <init-param> - <param-name>reload_on_mod</param-name> - <param-value>1</param-value> - </init-param> - <init-param> - <param-name>log_level</param-name> - <param-value>debug</param-value> -<!-- <param-value>info</param-value> --> -<!-- <param-value>warn</param-value> --> -<!-- <param-value>error</param-value> --> -<!-- <param-value>fatal</param-value> --> - </init-param> - <load-on-startup>1</load-on-startup> - </servlet> - - <servlet-mapping> - <servlet-name>modjy</servlet-name> - <url-pattern>/*</url-pattern> - </servlet-mapping> - -</web-app> Copied: trunk/jython/Demo/modjy_webapp/WEB-INF/web.xml (from rev 6070, branches/modjy/Demo/modjy_webapp/WEB-INF/web.xml) =================================================================== --- trunk/jython/Demo/modjy_webapp/WEB-INF/web.xml (rev 0) +++ trunk/jython/Demo/modjy_webapp/WEB-INF/web.xml 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!DOCTYPE web-app + PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" + "http://java.sun.com/dtd/web-app_2_3.dtd"> +<web-app> + + <display-name>modjy demo application</display-name> + <description> + modjy WSGI demo application + </description> + + <servlet> + <servlet-name>modjy</servlet-name> + <servlet-class>com.xhaus.modjy.ModjyJServlet</servlet-class> + <init-param> + <param-name>python.home</param-name> + <param-value>C:/jython2.5</param-value> + </init-param> +<!-- + There are two different ways you can specify an application to modjy + 1. Using the app_import_name mechanism + 2. Using a combination of app_directory/app_filename/app_callable_name + Examples of both are given below + See the documenation for more details. + http://modjy.xhaus.com/locating.html#locating_callables +--> +<!-- + This is the app_import_name mechanism. If you specify a value + for this variable, then it will take precedence over the other mechanism + <init-param> + <param-name>app_import_name</param-name> + <param-value>my_wsgi_module.my_handler_class().handler_method</param-value> + </init-param> +--> +<!-- + And this is the app_directory/app_filename/app_callable_name combo + The defaults for these three variables are ""/application.py/handler + So if you specify no values at all for any of app_* variables, then modjy + will by default look for "handler" in "application.py" in the servlet + context root. + <init-param> + <param-name>app_directory</param-name> + <param-value>some_sub_directory</param-value> + </init-param> +--> + <init-param> + <param-name>app_filename</param-name> + <param-value>demo_app.py</param-value> + </init-param> +<!-- + Supply a value for this parameter if you want your application + callable to have a different name than the default. + <init-param> + <param-name>app_callable_name</param-name> + <param-value>my_handler_func</param-value> + </init-param> +--> + <!-- Do you want application callables to be cached? --> + <init-param> + <param-name>cache_callables</param-name> + <param-value>1</param-value> + </init-param> + <!-- Should the application be reloaded if it's .py file changes? --> + <!-- Does not work with the app_import_name mechanism --> + <init-param> + <param-name>reload_on_mod</param-name> + <param-value>1</param-value> + </init-param> + <init-param> + <param-name>log_level</param-name> + <param-value>debug</param-value> +<!-- <param-value>info</param-value> --> +<!-- <param-value>warn</param-value> --> +<!-- <param-value>error</param-value> --> +<!-- <param-value>fatal</param-value> --> + </init-param> + <load-on-startup>1</load-on-startup> + </servlet> + + <servlet-mapping> + <servlet-name>modjy</servlet-name> + <url-pattern>/*</url-pattern> + </servlet-mapping> + +</web-app> Deleted: trunk/jython/Demo/modjy_webapp/demo_app.py =================================================================== --- branches/modjy/Demo/modjy_webapp/demo_app.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Demo/modjy_webapp/demo_app.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,37 +0,0 @@ -import sys - -def escape_html(s): return s.replace('&', '&').replace('<', '<').replace('>', '>') - -def cutoff(s, n=100): - if len(s) > n: return s[:n]+ '.. cut ..' - return s - -def handler(environ, start_response): - writer = start_response("200 OK", [ ('content-type', 'text/html') ]) - response_parts = [] - response_parts.append("<html>") - response_parts.append("<head>") - response_parts.append("<title>Modjy demo application</title>") - response_parts.append("</head>") - response_parts.append("<body>") - response_parts.append("<p>Modjy servlet running correctly: jython %s on %s:</p>" % (sys.version, sys.platform)) - response_parts.append("<h3>Hello WSGI World!</h3>") - response_parts.append("<h4>Here are the contents of the WSGI environment</h4>") - environ_str = "<table border='1'>" - keys = environ.keys() - keys.sort() - for ix, name in enumerate(keys): - if ix % 2: - background='#ffffff' - else: - background='#eeeeee' - style = " style='background-color:%s;'" % background - value = escape_html(cutoff(str(environ[name]))) or ' ' - environ_str = "%s\n<tr><td%s>%s</td><td%s>%s</td></tr>" % \ - (environ_str, style, name, style, value) - environ_str = "%s\n</table>" % environ_str - response_parts.append(environ_str) - response_parts.append("</body>") - response_parts.append("</html>") - response_text = "\n".join(response_parts) - return [response_text] Copied: trunk/jython/Demo/modjy_webapp/demo_app.py (from rev 6070, branches/modjy/Demo/modjy_webapp/demo_app.py) =================================================================== --- trunk/jython/Demo/modjy_webapp/demo_app.py (rev 0) +++ trunk/jython/Demo/modjy_webapp/demo_app.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,37 @@ +import sys + +def escape_html(s): return s.replace('&', '&').replace('<', '<').replace('>', '>') + +def cutoff(s, n=100): + if len(s) > n: return s[:n]+ '.. cut ..' + return s + +def handler(environ, start_response): + writer = start_response("200 OK", [ ('content-type', 'text/html') ]) + response_parts = [] + response_parts.append("<html>") + response_parts.append("<head>") + response_parts.append("<title>Modjy demo application</title>") + response_parts.append("</head>") + response_parts.append("<body>") + response_parts.append("<p>Modjy servlet running correctly: jython %s on %s:</p>" % (sys.version, sys.platform)) + response_parts.append("<h3>Hello WSGI World!</h3>") + response_parts.append("<h4>Here are the contents of the WSGI environment</h4>") + environ_str = "<table border='1'>" + keys = environ.keys() + keys.sort() + for ix, name in enumerate(keys): + if ix % 2: + background='#ffffff' + else: + background='#eeeeee' + style = " style='background-color:%s;'" % background + value = escape_html(cutoff(str(environ[name]))) or ' ' + environ_str = "%s\n<tr><td%s>%s</td><td%s>%s</td></tr>" % \ + (environ_str, style, name, style, value) + environ_str = "%s\n</table>" % environ_str + response_parts.append(environ_str) + response_parts.append("</body>") + response_parts.append("</html>") + response_text = "\n".join(response_parts) + return [response_text] Deleted: trunk/jython/Demo/modjy_webapp/readme.txt =================================================================== --- branches/modjy/Demo/modjy_webapp/readme.txt 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Demo/modjy_webapp/readme.txt 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,15 +0,0 @@ -To deploy this application - -1. Copy the jython.jar file into the WEB-INF/lib subdirectory -2. Set the value of python.home property in WEB-INF/web.xml so - that it points to your jython installation. -3. Copy this directory to the applications directory of your servlet - container. On Apache Tomcat, this is the "webapps" subdirectory - of the tomcat install directory. -4. Enter the URL http://localhost:8080/modjy_webapp into your - browser. -5. You should see a table containing the WSGI environment. - -Please see the installation documentation for more details. - -http://modjy.xhaus.com/install.html Copied: trunk/jython/Demo/modjy_webapp/readme.txt (from rev 6070, branches/modjy/Demo/modjy_webapp/readme.txt) =================================================================== --- trunk/jython/Demo/modjy_webapp/readme.txt (rev 0) +++ trunk/jython/Demo/modjy_webapp/readme.txt 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,15 @@ +To deploy this application + +1. Copy the jython.jar file into the WEB-INF/lib subdirectory +2. Set the value of python.home property in WEB-INF/web.xml so + that it points to your jython installation. +3. Copy this directory to the applications directory of your servlet + container. On Apache Tomcat, this is the "webapps" subdirectory + of the tomcat install directory. +4. Enter the URL http://localhost:8080/modjy_webapp into your + browser. +5. You should see a table containing the WSGI environment. + +Please see the installation documentation for more details. + +http://modjy.xhaus.com/install.html Deleted: trunk/jython/Lib/modjy/__init__.py =================================================================== --- branches/modjy/Lib/modjy/__init__.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Lib/modjy/__init__.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,22 +0,0 @@ -### -# -# Copyright Alan Kennedy. -# -# You may contact the copyright holder at this uri: -# -# http://www.xhaus.com/contact/modjy -# -# The licence under which this code is released is the Apache License v2.0. -# -# The terms and conditions of this license are listed in a file contained -# in the distribution that also contained this file, under the name -# LICENSE.txt. -# -# You may also read a copy of the license at the following web address. -# -# http://modjy.xhaus.com/LICENSE.txt -# -### - -__all__ = ['modjy', 'modjy_exceptions', 'modjy_impl', 'modjy_log', 'modjy_params', 'modjy_publish', 'modjy_response', 'modjy_write', 'modjy_wsgi',] - Copied: trunk/jython/Lib/modjy/__init__.py (from rev 6070, branches/modjy/Lib/modjy/__init__.py) =================================================================== --- trunk/jython/Lib/modjy/__init__.py (rev 0) +++ trunk/jython/Lib/modjy/__init__.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,22 @@ +### +# +# Copyright Alan Kennedy. +# +# You may contact the copyright holder at this uri: +# +# http://www.xhaus.com/contact/modjy +# +# The licence under which this code is released is the Apache License v2.0. +# +# The terms and conditions of this license are listed in a file contained +# in the distribution that also contained this file, under the name +# LICENSE.txt. +# +# You may also read a copy of the license at the following web address. +# +# http://modjy.xhaus.com/LICENSE.txt +# +### + +__all__ = ['modjy', 'modjy_exceptions', 'modjy_impl', 'modjy_log', 'modjy_params', 'modjy_publish', 'modjy_response', 'modjy_write', 'modjy_wsgi',] + Deleted: trunk/jython/Lib/modjy/modjy.py =================================================================== --- branches/modjy/Lib/modjy/modjy.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Lib/modjy/modjy.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,121 +0,0 @@ -### -# -# Copyright Alan Kennedy. -# -# You may contact the copyright holder at this uri: -# -# http://www.xhaus.com/contact/modjy -# -# The licence under which this code is released is the Apache License v2.0. -# -# The terms and conditions of this license are listed in a file contained -# in the distribution that also contained this file, under the name -# LICENSE.txt. -# -# You may also read a copy of the license at the following web address. -# -# http://modjy.xhaus.com/LICENSE.txt -# -### - -import jarray -import synchronize -import sys -import types - -sys.add_package("javax.servlet") -sys.add_package("javax.servlet.http") -sys.add_package("org.python.core") - -from modjy_exceptions import * -from modjy_log import * -from modjy_params import modjy_param_mgr, modjy_servlet_params -from modjy_wsgi import modjy_wsgi -from modjy_response import start_response_object -from modjy_impl import modjy_impl -from modjy_publish import modjy_publisher - -from javax.servlet.http import HttpServlet - -class modjy_servlet(HttpServlet, modjy_publisher, modjy_wsgi, modjy_impl): - - def __init__(self): - HttpServlet.__init__(self) - - def do_param(self, name, value): - if name[:3] == 'log': - getattr(self.log, "set_%s" % name)(value) - else: - self.params[name] = value - - def process_param_container(self, param_container): - param_enum = param_container.getInitParameterNames() - while param_enum.hasMoreElements(): - param_name = param_enum.nextElement() - self.do_param(param_name, param_container.getInitParameter(param_name)) - - def get_params(self): - self.process_param_container(self.servlet_context) - self.process_param_container(self.servlet) - - def init(self, delegator): - self.servlet = delegator - self.servlet_context = self.servlet.getServletContext() - self.servlet_config = self.servlet.getServletConfig() - self.log = modjy_logger(self.servlet_context) - self.params = modjy_param_mgr(modjy_servlet_params) - self.get_params() - self.init_impl() - self.init_publisher() - import modjy_exceptions - self.exc_handler = getattr(modjy_exceptions, '%s_handler' % self.params['exc_handler'])() - - def service (self, req, resp): - wsgi_environ = {} - try: - self.dispatch_to_application(req, resp, wsgi_environ) - except ModjyException, mx: - self.log.error("Exception servicing request: %s" % str(mx)) - typ, value, tb = sys.exc_info()[:] - self.exc_handler.handle(req, resp, wsgi_environ, mx, (typ, value, tb) ) - - def get_j2ee_ns(self, req, resp): - return { - 'servlet': self.servlet, - 'servlet_context': self.servlet_context, - 'servlet_config': self.servlet_config, - 'request': req, - 'response': resp, - } - - def dispatch_to_application(self, req, resp, environ): - app_callable = self.get_app_object(req, environ) - self.set_wsgi_environment(req, resp, environ, self.params, self.get_j2ee_ns(req, resp)) - response_callable = start_response_object(req, resp) - try: - app_return = self.call_application(app_callable, environ, response_callable) - if app_return is None: - raise ReturnNotIterable("Application returned None: must return an iterable") - self.deal_with_app_return(environ, response_callable, app_return) - except ModjyException, mx: - self.raise_exc(mx.__class__, str(mx)) - except Exception, x: - self.raise_exc(ApplicationException, str(x)) - - def call_application(self, app_callable, environ, response_callable): - if self.params['multithread']: - return app_callable.__call__(environ, response_callable) - else: - return synchronize.apply_synchronized( \ - app_callable, \ - app_callable, \ - (environ, response_callable)) - - def expand_relative_path(self, path): - if path.startswith("$"): - return self.servlet.getServletContext().getRealPath(path[1:]) - return path - - def raise_exc(self, exc_class, message): - self.log.error(message) - raise exc_class(message) Copied: trunk/jython/Lib/modjy/modjy.py (from rev 6070, branches/modjy/Lib/modjy/modjy.py) =================================================================== --- trunk/jython/Lib/modjy/modjy.py (rev 0) +++ trunk/jython/Lib/modjy/modjy.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,121 @@ +### +# +# Copyright Alan Kennedy. +# +# You may contact the copyright holder at this uri: +# +# http://www.xhaus.com/contact/modjy +# +# The licence under which this code is released is the Apache License v2.0. +# +# The terms and conditions of this license are listed in a file contained +# in the distribution that also contained this file, under the name +# LICENSE.txt. +# +# You may also read a copy of the license at the following web address. +# +# http://modjy.xhaus.com/LICENSE.txt +# +### + +import jarray +import synchronize +import sys +import types + +sys.add_package("javax.servlet") +sys.add_package("javax.servlet.http") +sys.add_package("org.python.core") + +from modjy_exceptions import * +from modjy_log import * +from modjy_params import modjy_param_mgr, modjy_servlet_params +from modjy_wsgi import modjy_wsgi +from modjy_response import start_response_object +from modjy_impl import modjy_impl +from modjy_publish import modjy_publisher + +from javax.servlet.http import HttpServlet + +class modjy_servlet(HttpServlet, modjy_publisher, modjy_wsgi, modjy_impl): + + def __init__(self): + HttpServlet.__init__(self) + + def do_param(self, name, value): + if name[:3] == 'log': + getattr(self.log, "set_%s" % name)(value) + else: + self.params[name] = value + + def process_param_container(self, param_container): + param_enum = param_container.getInitParameterNames() + while param_enum.hasMoreElements(): + param_name = param_enum.nextElement() + self.do_param(param_name, param_container.getInitParameter(param_name)) + + def get_params(self): + self.process_param_container(self.servlet_context) + self.process_param_container(self.servlet) + + def init(self, delegator): + self.servlet = delegator + self.servlet_context = self.servlet.getServletContext() + self.servlet_config = self.servlet.getServletConfig() + self.log = modjy_logger(self.servlet_context) + self.params = modjy_param_mgr(modjy_servlet_params) + self.get_params() + self.init_impl() + self.init_publisher() + import modjy_exceptions + self.exc_handler = getattr(modjy_exceptions, '%s_handler' % self.params['exc_handler'])() + + def service (self, req, resp): + wsgi_environ = {} + try: + self.dispatch_to_application(req, resp, wsgi_environ) + except ModjyException, mx: + self.log.error("Exception servicing request: %s" % str(mx)) + typ, value, tb = sys.exc_info()[:] + self.exc_handler.handle(req, resp, wsgi_environ, mx, (typ, value, tb) ) + + def get_j2ee_ns(self, req, resp): + return { + 'servlet': self.servlet, + 'servlet_context': self.servlet_context, + 'servlet_config': self.servlet_config, + 'request': req, + 'response': resp, + } + + def dispatch_to_application(self, req, resp, environ): + app_callable = self.get_app_object(req, environ) + self.set_wsgi_environment(req, resp, environ, self.params, self.get_j2ee_ns(req, resp)) + response_callable = start_response_object(req, resp) + try: + app_return = self.call_application(app_callable, environ, response_callable) + if app_return is None: + raise ReturnNotIterable("Application returned None: must return an iterable") + self.deal_with_app_return(environ, response_callable, app_return) + except ModjyException, mx: + self.raise_exc(mx.__class__, str(mx)) + except Exception, x: + self.raise_exc(ApplicationException, str(x)) + + def call_application(self, app_callable, environ, response_callable): + if self.params['multithread']: + return app_callable.__call__(environ, response_callable) + else: + return synchronize.apply_synchronized( \ + app_callable, \ + app_callable, \ + (environ, response_callable)) + + def expand_relative_path(self, path): + if path.startswith("$"): + return self.servlet.getServletContext().getRealPath(path[1:]) + return path + + def raise_exc(self, exc_class, message): + self.log.error(message) + raise exc_class(message) Deleted: trunk/jython/Lib/modjy/modjy_exceptions.py =================================================================== --- branches/modjy/Lib/modjy/modjy_exceptions.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Lib/modjy/modjy_exceptions.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,91 +0,0 @@ -### -# -# Copyright Alan Kennedy. -# -# You may contact the copyright holder at this uri: -# -# http://www.xhaus.com/contact/modjy -# -# The licence under which this code is released is the Apache License v2.0. -# -# The terms and conditions of this license are listed in a file contained -# in the distribution that also contained this file, under the name -# LICENSE.txt. -# -# You may also read a copy of the license at the following web address. -# -# http://modjy.xhaus.com/LICENSE.txt -# -### - -import sys -import StringIO -import traceback - -from java.lang import IllegalStateException -from java.io import IOException -from javax.servlet import ServletException - -class ModjyException(Exception): pass - -class ModjyIOException(ModjyException): pass - -class ConfigException(ModjyException): pass -class BadParameter(ConfigException): pass -class ApplicationNotFound(ConfigException): pass -class NoCallable(ConfigException): pass - -class RequestException(ModjyException): pass - -class ApplicationException(ModjyException): pass -class StartResponseNotCalled(ApplicationException): pass -class StartResponseCalledTwice(ApplicationException): pass -class ResponseCommitted(ApplicationException): pass -class HopByHopHeaderSet(ApplicationException): pass -class WrongLength(ApplicationException): pass -class BadArgument(ApplicationException): pass -class ReturnNotIterable(ApplicationException): pass -class NonStringOutput(ApplicationException): pass - -class exception_handler: - - def handle(self, req, resp, environ, exc, exc_info): - pass - - def get_status_and_message(self, req, resp, exc): - return resp.SC_INTERNAL_SERVER_ERROR, "Server configuration error" - -# -# Special exception handler for testing -# - -class testing_handler(exception_handler): - - def handle(self, req, resp, environ, exc, exc_info): - typ, value, tb = exc_info - err_msg = StringIO.StringIO() - err_msg.write("%s: %s\n" % (typ, value,) ) - err_msg.write(">Environment\n") - for k in environ.keys(): - err_msg.write("%s=%s\n" % (k, repr(environ[k])) ) - err_msg.write("<Environment\n") - err_msg.write(">TraceBack\n") - for line in traceback.format_exception(typ, value, tb): - err_msg.write(line) - err_msg.write("<TraceBack\n") - try: - status, message = self.get_status_and_message(req, resp, exc) - resp.setStatus(status) - resp.setContentLength(len(err_msg.getvalue())) - resp.getOutputStream().write(err_msg.getvalue()) - except IllegalStateException, ise: - raise exc # Let the container deal with it - -# -# Standard exception handler -# - -class standard_handler(exception_handler): - - def handle(self, req, resp, environ, exc, exc_info): - raise exc_info[0], exc_info[1], exc_info[2] Copied: trunk/jython/Lib/modjy/modjy_exceptions.py (from rev 6070, branches/modjy/Lib/modjy/modjy_exceptions.py) =================================================================== --- trunk/jython/Lib/modjy/modjy_exceptions.py (rev 0) +++ trunk/jython/Lib/modjy/modjy_exceptions.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,91 @@ +### +# +# Copyright Alan Kennedy. +# +# You may contact the copyright holder at this uri: +# +# http://www.xhaus.com/contact/modjy +# +# The licence under which this code is released is the Apache License v2.0. +# +# The terms and conditions of this license are listed in a file contained +# in the distribution that also contained this file, under the name +# LICENSE.txt. +# +# You may also read a copy of the license at the following web address. +# +# http://modjy.xhaus.com/LICENSE.txt +# +### + +import sys +import StringIO +import traceback + +from java.lang import IllegalStateException +from java.io import IOException +from javax.servlet import ServletException + +class ModjyException(Exception): pass + +class ModjyIOException(ModjyException): pass + +class ConfigException(ModjyException): pass +class BadParameter(ConfigException): pass +class ApplicationNotFound(ConfigException): pass +class NoCallable(ConfigException): pass + +class RequestException(ModjyException): pass + +class ApplicationException(ModjyException): pass +class StartResponseNotCalled(ApplicationException): pass +class StartResponseCalledTwice(ApplicationException): pass +class ResponseCommitted(ApplicationException): pass +class HopByHopHeaderSet(ApplicationException): pass +class WrongLength(ApplicationException): pass +class BadArgument(ApplicationException): pass +class ReturnNotIterable(ApplicationException): pass +class NonStringOutput(ApplicationException): pass + +class exception_handler: + + def handle(self, req, resp, environ, exc, exc_info): + pass + + def get_status_and_message(self, req, resp, exc): + return resp.SC_INTERNAL_SERVER_ERROR, "Server configuration error" + +# +# Special exception handler for testing +# + +class testing_handler(exception_handler): + + def handle(self, req, resp, environ, exc, exc_info): + typ, value, tb = exc_info + err_msg = StringIO.StringIO() + err_msg.write("%s: %s\n" % (typ, value,) ) + err_msg.write(">Environment\n") + for k in environ.keys(): + err_msg.write("%s=%s\n" % (k, repr(environ[k])) ) + err_msg.write("<Environment\n") + err_msg.write(">TraceBack\n") + for line in traceback.format_exception(typ, value, tb): + err_msg.write(line) + err_msg.write("<TraceBack\n") + try: + status, message = self.get_status_and_message(req, resp, exc) + resp.setStatus(status) + resp.setContentLength(len(err_msg.getvalue())) + resp.getOutputStream().write(err_msg.getvalue()) + except IllegalStateException, ise: + raise exc # Let the container deal with it + +# +# Standard exception handler +# + +class standard_handler(exception_handler): + + def handle(self, req, resp, environ, exc, exc_info): + raise exc_info[0], exc_info[1], exc_info[2] Deleted: trunk/jython/Lib/modjy/modjy_impl.py =================================================================== --- branches/modjy/Lib/modjy/modjy_impl.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Lib/modjy/modjy_impl.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,101 +0,0 @@ -### -# -# Copyright Alan Kennedy. -# -# You may contact the copyright holder at this uri: -# -# http://www.xhaus.com/contact/modjy -# -# The licence under which this code is released is the Apache License v2.0. -# -# The terms and conditions of this license are listed in a file contained -# in the distribution that also contained this file, under the name -# LICENSE.txt. -# -# You may also read a copy of the license at the following web address. -# -# http://modjy.xhaus.com/LICENSE.txt -# -### - -import types -import sys - -from modjy_exceptions import * - -class modjy_impl: - - def deal_with_app_return(self, environ, start_response_callable, app_return): - self.log.debug("Processing app return type: %s" % str(type(app_return))) - if isinstance(app_return, types.StringTypes): - raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return))) - if type(app_return) is types.FileType: - pass # TBD: What to do here? can't call fileno() - if hasattr(app_return, '__len__') and callable(app_return.__len__): - expected_pieces = app_return.__len__() - else: - expected_pieces = -1 - try: - try: - ix = 0 - for next_piece in app_return: - if not isinstance(next_piece, types.StringTypes): - raise NonStringOutput("Application returned iterable containing non-strings: %s" % str(type(next_piece))) - if ix == 0: - # The application may have called start_response in the first iteration - if not start_response_callable.called: - raise StartResponseNotCalled("Start_response callable was never called.") - if not start_response_callable.content_length \ - and expected_pieces == 1 \ - and start_response_callable.write_callable.num_writes == 0: - # Take the length of the first piece - start_response_callable.set_content_length(len(next_piece)) - start_response_callable.write_callable(next_piece) - ix += 1 - if ix == expected_pieces: - break - if expected_pieces != -1 and ix != expected_pieces: - raise WrongLength("Iterator len() was wrong. Expected %d pieces: got %d" % (expected_pieces, ix) ) - except AttributeError, ax: - if str(ax) == "__getitem__": - raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return))) - else: - raise ax - except TypeError, tx: - raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return))) - except ModjyException, mx: - raise mx - except Exception, x: - raise ApplicationException(x) - finally: - if hasattr(app_return, 'close') and callable(app_return.close): - app_return.close() - - def init_impl(self): - self.do_j_env_params() - - def add_packages(self, package_list): - packages = [p.strip() for p in package_list.split(';')] - for p in packages: - self.log.info("Adding java package %s to jython" % p) - sys.add_package(p) - - def add_classdirs(self, classdir_list): - classdirs = [cd.strip() for cd in classdir_list.split(';')] - for cd in classdirs: - self.log.info("Adding directory %s to jython class file search path" % cd) - sys.add_classdir(cd) - - def add_extdirs(self, extdir_list): - extdirs = [ed.strip() for ed in extdir_list.split(';')] - for ed in extdirs: - self.log.info("Adding directory %s for .jars and .zips search path" % ed) - sys.add_extdir(self.expand_relative_path(ed)) - - def do_j_env_params(self): - if self.params['packages']: - self.add_packages(self.params['packages']) - if self.params['classdirs']: - self.add_classdirs(self.params['classdirs']) - if self.params['extdirs']: - self.add_extdirs(self.params['extdirs']) Copied: trunk/jython/Lib/modjy/modjy_impl.py (from rev 6070, branches/modjy/Lib/modjy/modjy_impl.py) =================================================================== --- trunk/jython/Lib/modjy/modjy_impl.py (rev 0) +++ trunk/jython/Lib/modjy/modjy_impl.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,101 @@ +### +# +# Copyright Alan Kennedy. +# +# You may contact the copyright holder at this uri: +# +# http://www.xhaus.com/contact/modjy +# +# The licence under which this code is released is the Apache License v2.0. +# +# The terms and conditions of this license are listed in a file contained +# in the distribution that also contained this file, under the name +# LICENSE.txt. +# +# You may also read a copy of the license at the following web address. +# +# http://modjy.xhaus.com/LICENSE.txt +# +### + +import types +import sys + +from modjy_exceptions import * + +class modjy_impl: + + def deal_with_app_return(self, environ, start_response_callable, app_return): + self.log.debug("Processing app return type: %s" % str(type(app_return))) + if isinstance(app_return, types.StringTypes): + raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return))) + if type(app_return) is types.FileType: + pass # TBD: What to do here? can't call fileno() + if hasattr(app_return, '__len__') and callable(app_return.__len__): + expected_pieces = app_return.__len__() + else: + expected_pieces = -1 + try: + try: + ix = 0 + for next_piece in app_return: + if not isinstance(next_piece, types.StringTypes): + raise NonStringOutput("Application returned iterable containing non-strings: %s" % str(type(next_piece))) + if ix == 0: + # The application may have called start_response in the first iteration + if not start_response_callable.called: + raise StartResponseNotCalled("Start_response callable was never called.") + if not start_response_callable.content_length \ + and expected_pieces == 1 \ + and start_response_callable.write_callable.num_writes == 0: + # Take the length of the first piece + start_response_callable.set_content_length(len(next_piece)) + start_response_callable.write_callable(next_piece) + ix += 1 + if ix == expected_pieces: + break + if expected_pieces != -1 and ix != expected_pieces: + raise WrongLength("Iterator len() was wrong. Expected %d pieces: got %d" % (expected_pieces, ix) ) + except AttributeError, ax: + if str(ax) == "__getitem__": + raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return))) + else: + raise ax + except TypeError, tx: + raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return))) + except ModjyException, mx: + raise mx + except Exception, x: + raise ApplicationException(x) + finally: + if hasattr(app_return, 'close') and callable(app_return.close): + app_return.close() + + def init_impl(self): + self.do_j_env_params() + + def add_packages(self, package_list): + packages = [p.strip() for p in package_list.split(';')] + for p in packages: + self.log.info("Adding java package %s to jython" % p) + sys.add_package(p) + + def add_classdirs(self, classdir_list): + classdirs = [cd.strip() for cd in classdir_list.split(';')] + for cd in classdirs: + self.log.info("Adding directory %s to jython class file search path" % cd) + sys.add_classdir(cd) + + def add_extdirs(self, extdir_list): + extdirs = [ed.strip() for ed in extdir_list.split(';')] + for ed in extdirs: + self.log.info("Adding directory %s for .jars and .zips search path" % ed) + sys.add_extdir(self.expand_relative_path(ed)) + + def do_j_env_params(self): + if self.params['packages']: + self.add_packages(self.params['packages']) + if self.params['classdirs']: + self.add_classdirs(self.params['classdirs']) + if self.params['extdirs']: + self.add_extdirs(self.params['extdirs']) Deleted: trunk/jython/Lib/modjy/modjy_log.py =================================================================== --- branches/modjy/Lib/modjy/modjy_log.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Lib/modjy/modjy_log.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,80 +0,0 @@ -### -# -# Copyright Alan Kennedy. -# -# You may contact the copyright holder at this uri: -# -# http://www.xhaus.com/contact/modjy -# -# The licence under which this code is released is the Apache License v2.0. -# -# The terms and conditions of this license are listed in a file contained -# in the distribution that also contained this file, under the name -# LICENSE.txt. -# -# You may also read a copy of the license at the following web address. -# -# http://modjy.xhaus.com/LICENSE.txt -# -### - -import java - -import sys - -DEBUG = 'debug' -INFO = 'info' -WARN = 'warn' -ERROR = 'error' -FATAL = 'fatal' - -levels_dict = {} -ix = 0 -for level in [DEBUG, INFO, WARN, ERROR, FATAL, ]: - levels_dict[level]=ix - ix += 1 - -class modjy_logger: - - def __init__(self, context): - self.log_ctx = context - self.format_str = "%(lvl)s:\t%(msg)s" - self.log_level = levels_dict[DEBUG] - - def _log(self, level, level_str, msg, exc): - if level >= self.log_level: - msg = self.format_str % {'lvl': level_str, 'msg': msg, } - if exc: -# java.lang.System.err.println(msg, exc) - self.log_ctx.log(msg, exc) - else: -# java.lang.System.err.println(msg) - self.log_ctx.log(msg) - - def debug(self, msg, exc=None): - self._log(0, DEBUG, msg, exc) - - def info(self, msg, exc=None): - self._log(1, INFO, msg, exc) - - def warn(self, msg, exc=None): - self._log(2, WARN, msg, exc) - - def error(self, msg, exc=None): - self._log(3, ERROR, msg, exc) - - def fatal(self, msg, exc=None): - self._log(4, FATAL, msg, exc) - - def set_log_level(self, level_string): - try: - self.log_level = levels_dict[level_string] - except KeyError: - raise BadParameter("Invalid log level: '%s'" % level_string) - - def set_log_format(self, format_string): - # BUG! Format string never actually used in this function. - try: - self._log(debug, "This is a log formatting test", None) - except KeyError: - raise BadParameter("Bad format string: '%s'" % format_string) Copied: trunk/jython/Lib/modjy/modjy_log.py (from rev 6070, branches/modjy/Lib/modjy/modjy_log.py) =================================================================== --- trunk/jython/Lib/modjy/modjy_log.py (rev 0) +++ trunk/jython/Lib/modjy/modjy_log.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,80 @@ +### +# +# Copyright Alan Kennedy. +# +# You may contact the copyright holder at this uri: +# +# http://www.xhaus.com/contact/modjy +# +# The licence under which this code is released is the Apache License v2.0. +# +# The terms and conditions of this license are listed in a file contained +# in the distribution that also contained this file, under the name +# LICENSE.txt. +# +# You may also read a copy of the license at the following web address. +# +# http://modjy.xhaus.com/LICENSE.txt +# +### + +import java + +import sys + +DEBUG = 'debug' +INFO = 'info' +WARN = 'warn' +ERROR = 'error' +FATAL = 'fatal' + +levels_dict = {} +ix = 0 +for level in [DEBUG, INFO, WARN, ERROR, FATAL, ]: + levels_dict[level]=ix + ix += 1 + +class modjy_logger: + + def __init__(self, context): + self.log_ctx = context + self.format_str = "%(lvl)s:\t%(msg)s" + self.log_level = levels_dict[DEBUG] + + def _log(self, level, level_str, msg, exc): + if level >= self.log_level: + msg = self.format_str % {'lvl': level_str, 'msg': msg, } + if exc: +# java.lang.System.err.println(msg, exc) + self.log_ctx.log(msg, exc) + else: +# java.lang.System.err.println(msg) + self.log_ctx.log(msg) + + def debug(self, msg, exc=None): + self._log(0, DEBUG, msg, exc) + + def info(self, msg, exc=None): + self._log(1, INFO, msg, exc) + + def warn(self, msg, exc=None): + self._log(2, WARN, msg, exc) + + def error(self, msg, exc=None): + self._log(3, ERROR, msg, exc) + + def fatal(self, msg, exc=None): + self._log(4, FATAL, msg, exc) + + def set_log_level(self, level_string): + try: + self.log_level = levels_dict[level_string] + except KeyError: + raise BadParameter("Invalid log level: '%s'" % level_string) + + def set_log_format(self, format_string): + # BUG! Format string never actually used in this function. + try: + self._log(debug, "This is a log formatting test", None) + except KeyError: + raise BadParameter("Bad format string: '%s'" % format_string) Deleted: trunk/jython/Lib/modjy/modjy_params.py =================================================================== --- branches/modjy/Lib/modjy/modjy_params.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Lib/modjy/modjy_params.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,84 +0,0 @@ -### -# -# Copyright Alan Kennedy. -# -# You may contact the copyright holder at this uri: -# -# http://www.xhaus.com/contact/modjy -# -# The licence under which this code is released is the Apache License v2.0. -# -# The terms and conditions of this license are listed in a file contained -# in the distribution that also contained this file, under the name -# LICENSE.txt. -# -# You may also read a copy of the license at the following web address. -# -# http://modjy.xhaus.com/LICENSE.txt -# -### - -from UserDict import UserDict - -BOOLEAN = ('boolean', int) -INTEGER = ('integer', int) -FLOAT = ('float', float) -STRING = ('string', None) - -modjy_servlet_params = { - - 'multithread': (BOOLEAN, 1), - 'cache_callables': (BOOLEAN, 1), - 'reload_on_mod': (BOOLEAN, 0), - - 'app_import_name': (STRING, None), - - 'app_directory': (STRING, None), - 'app_filename': (STRING, 'application.py'), - 'app_callable_name': (STRING, 'handler'), - 'callable_query_name': (STRING, None), - - 'exc_handler': (STRING, 'standard'), - - 'log_level': (STRING, 'info'), - - 'packages': (STRING, None), - 'classdirs': (STRING, None), - 'extdirs': (STRING, None), - - 'initial_env': (STRING, None), -} - -class modjy_param_mgr(UserDict): - - def __init__(self, param_types): - UserDict.__init__(self) - self.param_types = param_types - for pname in self.param_types.keys(): - typ, default = self.param_types[pname] - self.__setitem__(pname, default) - - def __getitem__(self, name): - return self._get_defaulted_value(name) - - def __setitem__(self, name, value): - self.data[name] = self._convert_value(name, value) - - def _convert_value(self, name, value): - if self.param_types.has_key(name): - typ, default = self.param_types[name] - typ_str, typ_func = typ - if typ_func: - try: - return typ_func(value) - except ValueError: - raise BadParameter("Illegal value for %s parameter '%s': %s" % (typ_str, name, value) ) - return value - - def _get_defaulted_value(self, name): - if self.data.has_key(name): - return self.data[name] - if self.param_types.has_key(name): - typ, default = self.param_types[name] - return default - raise KeyError(name) Copied: trunk/jython/Lib/modjy/modjy_params.py (from rev 6070, branches/modjy/Lib/modjy/modjy_params.py) =================================================================== --- trunk/jython/Lib/modjy/modjy_params.py (rev 0) +++ trunk/jython/Lib/modjy/modjy_params.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -0,0 +1,84 @@ +### +# +# Copyright Alan Kennedy. +# +# You may contact the copyright holder at this uri: +# +# http://www.xhaus.com/contact/modjy +# +# The licence under which this code is released is the Apache License v2.0. +# +# The terms and conditions of this license are listed in a file contained +# in the distribution that also contained this file, under the name +# LICENSE.txt. +# +# You may also read a copy of the license at the following web address. +# +# http://modjy.xhaus.com/LICENSE.txt +# +### + +from UserDict import UserDict + +BOOLEAN = ('boolean', int) +INTEGER = ('integer', int) +FLOAT = ('float', float) +STRING = ('string', None) + +modjy_servlet_params = { + + 'multithread': (BOOLEAN, 1), + 'cache_callables': (BOOLEAN, 1), + 'reload_on_mod': (BOOLEAN, 0), + + 'app_import_name': (STRING, None), + + 'app_directory': (STRING, None), + 'app_filename': (STRING, 'application.py'), + 'app_callable_name': (STRING, 'handler'), + 'callable_query_name': (STRING, None), + + 'exc_handler': (STRING, 'standard'), + + 'log_level': (STRING, 'info'), + + 'packages': (STRING, None), + 'classdirs': (STRING, None), + 'extdirs': (STRING, None), + + 'initial_env': (STRING, None), +} + +class modjy_param_mgr(UserDict): + + def __init__(self, param_types): + UserDict.__init__(self) + self.param_types = param_types + for pname in self.param_types.keys(): + typ, default = self.param_types[pname] + self.__setitem__(pname, default) + + def __getitem__(self, name): + return self._get_defaulted_value(name) + + def __setitem__(self, name, value): + self.data[name] = self._convert_value(name, value) + + def _convert_value(self, name, value): + if self.param_types.has_key(name): + typ, default = self.param_types[name] + typ_str, typ_func = typ + if typ_func: + try: + return typ_func(value) + except ValueError: + raise BadParameter("Illegal value for %s parameter '%s': %s" % (typ_str, name, value) ) + return value + + def _get_defaulted_value(self, name): + if self.data.has_key(name): + return self.data[name] + if self.param_types.has_key(name): + typ, default = self.param_types[name] + return default + raise KeyError(name) Deleted: trunk/jython/Lib/modjy/modjy_publish.py =================================================================== --- branches/modjy/Lib/modjy/modjy_publish.py 2009-03-05 22:07:35 UTC (rev 6070) +++ trunk/jython/Lib/modjy/modjy_publish.py 2009-03-06 18:27:15 UTC (rev 6075) @@ -1,138 +0,0 @@ -### -# -# Copyright Alan Kennedy. -# -# You may contact the copyright holder at this uri: -# -# http://www.xhaus.com/contact/modjy -# -# The licence under which this code is released is the Apache License v2.0. -# -# The terms and conditions of this license are listed in a file contained -# in the distribution that also contained this file, under the name -# LICENSE.txt. -# -# You may also read a copy of the license at the following web address. -# -# http://modjy.xhaus.com/LICENSE.txt -# -### - -import sys -import synchronize - -from java.io import File - -from modjy_exceptions import * - -class modjy_publisher: - - def init_publisher(self): - self.cache = None - if self.params['app_directory']: - self.app_directory = self.expand_relative_path(self.params['app_directory']) - else: - self.app_directory = self.servlet_context.getRealPath('/') - self.params['app_directory'] = self.app_directory - if not self.app_directory in sys.path: - sys.path.append(self.app_directory) - - def map_uri(self, req, environ): - source_uri = '%s%s%s' % (self.app_directory, File.separator, self.params['app_filename']) - callable_name = self.params['app_callable_name'] - if self.params['callable_query_name']: - query_string = req.getQueryString() - if query_string and '=' in query_string: - for name_val in query_string.split('&'): - name, value = name_val.split('=') - if name == self.params['callable_query_name']: - callable_name = value - return source_uri, callable_name - - def get_app_object(self, req, environ): - environ["SCRIPT_NAME"] = "%s%s" % (req.getContextPath(), req.getServletPath()) - path_info = req.getPathInfo() or "" - environ["PATH_INFO"] = path_info - environ["PATH_TRANSLATED"] = File(self.app_directory, path_info).getPath() - - if self.params['app_import_name'] is not None: - return self.get_app_object_importable(self.params['app_import_name']) - else: - if self.cache is None: - self.cache = {} - return self.get_app_object_old_style(req, environ) - - get_app_object = synchronize.make_synchronized(get_app_object) - - def get_app_object_importable(self, importable_name): - self.log.debug("Attempting to import application callable '%s'\n" % (importable_name, )) - # Under the importable mechanism, the cache contains a single object - if self.cache is None: - application, instantiable, method_name = self.load_importable(importable_name.strip()) - if instantiable and self.params['cache_callables']: - application = application() - self.cache = application, instantiable, method_name - application, instantiable, method_name = self.cache - self.log.debug("Application is " + str(application)) - if instantiable and not self.params['cache_callables']: - application = application() - self.log.debug("Instantiated application is " + str(application)) - if method_name is not None: - if not hasattr(application, method_name): - self.log.fatal("Attribute error application callable '%s' as no method '%s'" % (application, method_name)) - self.raise_exc(ApplicationNotFound, "Attribute error application callable '%s' as no method '%s'" % (application, method_name)) - application = getattr(application, method_name) - self.log.debug("Application method is " + str(application)) - return application - - def load_importable(sel... [truncated message content] |
From: <fwi...@us...> - 2009-03-07 04:16:09
|
Revision: 6079 http://jython.svn.sourceforge.net/jython/?rev=6079&view=rev Author: fwierzbicki Date: 2009-03-07 04:16:00 +0000 (Sat, 07 Mar 2009) Log Message: ----------- increment APIVersion, take --verify out of build.xml Modified Paths: -------------- trunk/jython/build.xml trunk/jython/src/org/python/core/imp.java Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-03-07 04:05:04 UTC (rev 6078) +++ trunk/jython/build.xml 2009-03-07 04:16:00 UTC (rev 6079) @@ -831,7 +831,6 @@ <target name="regrtest" depends="developer-build,regrtest-unix,regrtest-windows"/> <target name="regrtest-unix" if="os.family.unix"> <exec executable="${dist.dir}/bin/jython"> - <arg value="--verify"/> <arg value="-J${regrtest.Xmx}"/> <arg value="${dist.dir}/Lib/test/regrtest.py"/> <!-- Only run the tests that are expected to work on Jython --> Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2009-03-07 04:05:04 UTC (rev 6078) +++ trunk/jython/src/org/python/core/imp.java 2009-03-07 04:16:00 UTC (rev 6079) @@ -20,7 +20,7 @@ private static final String UNKNOWN_SOURCEFILE = "<unknown>"; - public static final int APIVersion = 17; + public static final int APIVersion = 18; public static final int NO_MTIME = -1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Oti <oh...@gm...> - 2009-03-07 08:07:31
|
On Sat, Mar 7, 2009 at 5:16 AM, <fwi...@us...> wrote: > Revision: 6079 > http://jython.svn.sourceforge.net/jython/?rev=6079&view=rev > Author: fwierzbicki > Date: 2009-03-07 04:16:00 +0000 (Sat, 07 Mar 2009) > > Log Message: > ----------- > increment APIVersion, take --verify out of build.xml Frank, thank you very much for helping me out here - i should have run the regrtests myself ! The waterfall buildbot also has --verify hardcoded (i assume). This is another proof that you can mess up a lot by changing the shell scripts... Oti. |
From: Frank W. <fwi...@gm...> - 2009-03-07 13:47:04
|
On Sat, Mar 7, 2009 at 3:07 AM, Oti <oh...@gm...> wrote: > On Sat, Mar 7, 2009 at 5:16 AM, <fwi...@us...> wrote: >> Revision: 6079 >> http://jython.svn.sourceforge.net/jython/?rev=6079&view=rev >> Author: fwierzbicki >> Date: 2009-03-07 04:16:00 +0000 (Sat, 07 Mar 2009) >> >> Log Message: >> ----------- >> increment APIVersion, take --verify out of build.xml > > Frank, > > thank you very much for helping me out here - i should have run the > regrtests myself ! No worries, I really appreciate how quickly you put this stuff together. I also appreciate your advocacy of new users. --boot is definitely the right way to go vs --verify. Thanks! -Frank |
From: <am...@us...> - 2009-03-07 15:35:58
|
Revision: 6080 http://jython.svn.sourceforge.net/jython/?rev=6080&view=rev Author: amak Date: 2009-03-07 15:35:39 +0000 (Sat, 07 Mar 2009) Log Message: ----------- Now that modjy is fully integrated, we no longer need the .zip version in extlibs. Modified Paths: -------------- trunk/jython/build.xml Removed Paths: ------------- trunk/jython/extlibs/modjy_0_25_3.zip Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-03-07 04:16:00 UTC (rev 6079) +++ trunk/jython/build.xml 2009-03-07 15:35:39 UTC (rev 6080) @@ -648,7 +648,6 @@ <include name="src/org/**/ucnhash.dat" /> <include name="grammar/*.g" /> <include name="extlibs/**/*.jar" /> - <include name="extlibs/**/*.zip" /> <include name="tests/java/**/*.java" /> <include name="CoreExposed.includes" /> </fileset> Deleted: trunk/jython/extlibs/modjy_0_25_3.zip =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-03-07 15:57:53
|
Revision: 6081 http://jython.svn.sourceforge.net/jython/?rev=6081&view=rev Author: fwierzbicki Date: 2009-03-07 15:57:43 +0000 (Sat, 07 Mar 2009) Log Message: ----------- Changing version numbers, README, plus some bugfix reports in NEWS (from some archeology on http://bugs.jython.org) Modified Paths: -------------- trunk/jython/NEWS trunk/jython/README.txt trunk/jython/build.xml Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2009-03-07 15:35:39 UTC (rev 6080) +++ trunk/jython/NEWS 2009-03-07 15:57:43 UTC (rev 6081) @@ -3,6 +3,291 @@ Jython 2.5 Bugs fixed (new numbering due to move to Roundup) - [ 1111 ] keyword arguments not supported on __import__ + - [ 1567212 ] Jython $py.class bytecode doesn't include the .py's mtime + - [ 1024 ] Jython $py.class bytecode doesn't include the .py's mtime + - [ 852818 ] Wrong error message when the second+ parameter to Java wrong + - [ 1222877 ] duplicate keyword arguments + - [ 1168 ] ast module not working + - [ 1192 ] deserialization of Jython classes extending Java classes fails when called from Java + - [ 1243 ] Running scripts from standalone jar with __run__.py broken + - [ 1237 ] Asnycore does not seem to work in Jython 2.5 (b0 or b1) + - [ 1257 ] Pickling (protocol 2) doesn't use overriden itervalues() on dict-derived classes + - [ 1245 ] modjy passes HTTP headers as unicode objects to the WSGI app + - [ 1258 ] select() semantics differ from CPython, causing pydoc HTTPd to fail + - [ 1043 ] Special broadcast host address <broadcast> is not supported. + - [ 1121 ] listening socket shutdown expects the wrong kind of socket + - [ 1244 ] Problem letting system choose the port for binding UDP socket + - [ 1241 ] Assignment to static variable shadows value + - [ 1234 ] Java classes' MRO resolution can throw an NPE + - [ 1231 ] 2.5b1 breaks XML DocumentBuilderFactory (in particular, Weblogic 10.3) + - [ 1230 ] importing with '*' from java packages does not work with 2.5b1 + - [ 1242 ] Tuples allow member assignment + - [ 1239 ] Package scanning seems to depend on import order in jython-2.5b1 + - [ 1235 ] java.awt.Frame - problem w/ attibutes + - [ 1240 ] Can't import _jython, but it's listed in the built-in modules + - [ 1217 ] decompressing a malformed stream with zlib results in a java.util.zip.DataFormatException instead of a zlib.error + - [ 1227 ] The cStringIO.StringIO.write implementation does not handle write/seek/write's correctly. + - [ 1232 ] Inherited java bean properties not recognized correctly + - [ 1229 ] os.utime fails in Jython2.5b1 + - [ 1228 ] Add version for 2.5b1 to Issue (Bug) tracker + - [ 1051 ] socket does not define AF_UNSPEC and AI_PASSIVE constants + - [ 1218 ] Socket timeouts on connect not honoured when timeout set through socket.setdefaulttimeout() + - [ 1747126 ] CLASSPATH not searched correctly for python source modules + - [ 1008 ] Jython broken on Java Web Start 1.6 + - [ 1181 ] Patch against trunk to make applets work again + - [ 1122 ] os.kill is not implemented + - [ 1154 ] socket.settimeout not working for recv + - [ 1171 ] Creating a PyFile from an InputStream is broken. + - [ 1211 ] Telnetlib.expect crashes when a timeout parameter is given. + - [ 1182 ] Patch to Lib/socket.py to fix broken SSL + - [ 1083 ] jython2.5a1 installer does not create "cachedir" directory + - [ 1063 ] RuntimeError expected when stack overflows + - [ 1205 ] list comprehension difference to python + - [ 1166 ] TypeError: utimes(): 3rd arg can't be coerced to long + - [ 1025 ] imp.find_module can't find builtin modules + - [ 1758318 ] StackOverflow if __nonzero__ returns self + - [ 1815110 ] eval and excec should accept mapping type for locals + - [ 600790 ] Overriding automatically defined methods + - [ 1201 ] Lack of Python line numbers in Java tracebacks + - [ 1658599 ] headless installation not detected + - [ 1161 ] imp.find_module can't find many modules (was: pylint & logilab ASTNG library) + - [ 1199 ] zipimporter should be smarter about what files it tries to access + - [ 1180 ] virtualenv broken on installed Jython + - [ 1196 ] failure of dir() on instances of a class with __getattribute__ + - [ 1194 ] with_statement: context __exit__ not called for return + - [ 1187 ] JYTHON_OPTS broken in jython.bat + - [ 1758319 ] bool should not be subclassable + - [ 1011 ] ant task to create launcher script + - [ 1137 ] ArrayType missing in Jython 2.5a3 + - [ 1058 ] Carlo Verre's object.__setattr__ hack allows modification of built in types + - [ 1222918 ] -C NONE causes exception + - [ 1604258 ] copy.copy doesn't work on subclasses of newstyle classes + - [ 1798554 ] zlib.__doc__ is not showing any output + - [ 1798556 ] patch for :[ 1798554 ] zlib.__doc__ is not showing any outpu + - [ 1003 ] struct packing inconsistent with CPython + - [ 1052 ] __int__ returning PyLong = ClassCastException mayhem + - [ 1167 ] random.py in standard library is broken in 2.5beta0 + - [ 1138 ] __file__ reflects original source location, not the pathname of the $py.class file + - [ 1174 ] NPE on PythonInterpreter.eval() + - [ 1173 ] undefined sys.prefix breaks initialization + - [ 1177 ] utf-8 codec isn't? + - [ 1835099 ] Bug in list.sort() + - [ 1141 ] Incorrect __import__ calls + - [ 1780767 ] Fix for [ 1768075 ] %c formats values outside of the + - [ 1115 ] __lt__ in a derived list produces a StackOverflowError + - [ 1062 ] Doctest does not work against unicode strings + - [ 1783868 ] __ge__ or __gt__ of subclass of str --> StackOverflowError + - [ 1125 ] not valid JAVA_HOME path + - [ 1777567 ] Type of reflected methods is different for Java and Python + - [ 513713 ] PyTableCode != PyCode + - [ 526672 ] inspect not supported + - [ 1754240 ] Error Message when attempting to bind to an in use Port + - [ 1159 ] custum number and float: unsupported operand type(s) for * + - [ 1158 ] compile() fails to recognize initial AST arg + - [ 1155 ] inet_ntoa missing from socket + - [ 1150 ] Nested generator expressions do not compile + - [ 1113 ] Syntax + Compiler Error + - [ 1157 ] Support pylint + - [ 1156 ] rfc822.py incompatible with PyFile(java.io.InputStream istream) + - [ 1128 ] java.lang.String should be mapped to PyUnicode, not PyString + - [ 1111 ] keyword arguments not supported on __import__ + - [ 1114 ] Compiler Error - null pointer + - [ 1134 ] Built-in functions should be of type types.BuiltinFunction + - [ 1075 ] os.rmdir deletes file + - [ 1136 ] Parsing a module fails if it ends with whitespace but no newline + - [ 1131 ] repr not 100% CPython compliant + - [ 1626844 ] fixes for failing binascii unit tests (2.3 branch) + - [ 1838658 ] 'platform' module is not available + - [ 1663711 ] 32767 characters is max string constant size + - [ 1847091 ] del statement doesn't work on builtin modules + - [ 1768969 ] filter doesn't return passed in subclass type + - [ 1047 ] xml.dom.pulldom doesn't work + - [ 1835109 ] Patch for [ 1835098 ] No decimal module available in jython + - [ 1768970 ] pyget used instead of __getitem__ in __iter__, filter + - [ 1768968 ] unicode bom isn't recognized to indicate unicode for parsing + - [ 1785475 ] patch for bug IDs 1768970, 1782565 & 1783868 + - [ 1738411 ] Unable to change function sys.settrace + - [ 1761111 ] Patch for PEP 292 Simpler String Substitutions + - [ 1835119 ] 'platform' module is not available in jython + - [ 1840479 ] coding: utf-8 and PEP 0263? + - [ 1835098 ] No decimal module available in jython + - [ 1717492 ] os.path.ismount incompletely implemented + - [ 1067 ] class / function call behaviour (Jython vs. CPython) + - [ 1091 ] Interactive Interpreter parser doesn't handle docstrings + - [ 1022 ] Class definitions aren't provided a __module__ variable + - [ 1120 ] invalid socket shutdown gives AssertionError, should be "transport endpoint not connected" socket.error + - [ 1119 ] socket module has no attribute SO_ERROR + - [ 1081 ] Jython 2.5a1 standalone installer hangs + - [ 1123 ] Weird "unexpected at this time" error. + - [ 1070 ] Standalone crashes with ZipException + - [ 1077 ] Standalone installation fails + - [ 1094 ] mismatched input class parsing error on "class" attributes of a java object + - [ 1015 ] unicode string combination with % behaves unexpectedly + - [ 1758279 ] Java classes exposed as Python classes but have no __module__ + - [ 1116 ] parser NPE on dotted (more than 1) attribute decorators + - [ 1758325 ] str's formatter doesn't raise TypeError if given wrong type + - [ 1095 ] AttributeError raised from __getattr__ method are swallowed + - [ 1106 ] os.getpid() call missing + - [ 1104 ] subprocess.Popen doesn't inherits os.environ to the spawned processes + - [ 1041 ] AttributeError raised from descriptors __get__ method are swallowed + - [ 1869347 ] TypeError while used derived class of long for comparison + - [ 1072 ] Parsing error in file with white space at the end + - [ 1045 ] PyBoolean.__tojava__(Object.class) should return a Boolean + - [ 1044 ] Patch to support for BigIntegers and PyLong on the PostgresqlDataHandler + - [ 1054 ] Patch: Fastpath for cursor.executemany() + - [ 1053 ] Better string interpolation with unicode args + - [ 1804011 ] classes extending dict can't be compared to dict + - [ 1889394 ] UnicodeDerived's == is broken + - [ 1060 ] deriveds don't support coerce + - [ 1650802 ] _csv module + - [ 1092 ] Parser problems on Django tree + - [ 1050 ] Don't display banner/prompts when stdin is not a tty + - [ 1069 ] setuptools: 'NoneType' object has no attribute 'startswith' + - [ 1093 ] Installer 2.5a1 on MS Windows: Incorrect jar is referred to in bin/jython + - [ 1605009 ] str subclasses can be used in raise + - [ 1079 ] twisted.python.threadable module: missing attribute '_RLock' + - [ 1088 ] Existing .py$class files from Jy2.2 cause error for Jy2.5a + - [ 1086 ] Handling of """quoted strings""" for 2.5a differs from Jy2.2 and Py2.5 + - [ 1087 ] assert error message at end of Python script differs from Py2.5 + - [ 1082 ] asm parser can't handle PySourceColor module + - [ 1767742 ] array.array('xx') should throw TypeError, not ValueError + - [ 1076 ] 2.5a1 jython.bat doesn't work from Windows explorer + - [ 1059 ] Possible to construct long(None) + - [ 1873148 ] list.__iadd__ not switching to __radd__ on NotImplemented + - [ 1056 ] Bad mro() overrides not caught + - [ 1886758 ] from __future__ import division leaks out of namespace + - [ 1879935 ] cPython/Jython different os.path.isabs() behavior + - [ 1879984 ] cPython/Jython different os.path.realpath() behavior + - [ 1879989 ] cPython/Jython different os.path.abspath() behavior + - [ 1605006 ] __doc__ descriptor on new style class returned directly + - [ 1639663 ] Patch for [ 1605006 ] __doc__ descriptor on new style class + - [ 1803960 ] Attribute Error :- 'slice' object has no attribute 'indice + - [ 1802863 ] zipfile.is_zipfile never returns False + - [ 678557 ] cgi parsing of multipart/form-data broken + - [ 1840038 ] patch for PyUnicode (fixes [ 1782565 ]) + - [ 1754222 ] raising SystemExit in a thread causes jython to quit + - [ 811908 ] OutOfMemoryError causes exit without a call to a handler + - [ 654142 ] NPE when converting __dict__ to list + - [ 515497 ] method instance not unique key in dict + - [ 718377 ] PyObject.__findattr_ throws NPE + - [ 753790 ] struct module inconsistent with CPython + - [ 1009477 ] Python collections should implement java interfaces + - [ 1599050 ] fileinput os.fstat fix + - [ 1676293 ] metaclass __init__ dct reference + - [ 1038 ] Custom KeyErrors raised from __getitem__ are swallowed + - [ 1039 ] AttributeError message on type instances doesn't match the CPython message + - [ 1048 ] List Comprehension in finally throws NPE + - [ 1037 ] float(None) throws AttributeError instead of TypeError + - [ 1814929 ] Patch for [ 1814904 ] dict.update() doesnt accept arguments + - [ 1814904 ] dict.update() doent accept the same arguments as constructor + - [ 947306 ] 2.3a0 bug in weakref.WeakValueDictionary + - [ 1016 ] Support socket.TCP_NODELAY + - [ 1033 ] zlib.adler32 computes wrong values + - [ 1797751 ] patch for :[ 1796272 ] partition and rpartition methods are + - [ 1796272 ] partition and rpartition methods are missing in jython + - [ 1040 ] KeyError.__str__ doesn't use repr() + - [ 1036 ] make Jython set pass (almost) all CPython tests + - [ 1035 ] set incorrectly raises TypeError when asked for superset/subset on non-set iterables + - [ 1034 ] can't supply dict() for globals in FunctionType() + - [ 1782565 ] Mismatch in repr of obj of unicode and subclass of unicode + - [ 1510227 ] difference between repr() and __repr__() + - [ 1501932 ] hasattr invokes __getattr__ + - [ 1775263 ] patch for bug [1768979]:hasattr,getattr + - [ 1768979 ] hasattr, getattr allow unicode identifiers + - [ 1780153 ] Fix for [ 1768075 ] %c formats values outside of the + - [ 1768075 ] %c formats values outside of the size of a single char + - [ 1803425 ] new builtin funcion :- sorted() - a new builtin sorted() act + - [ 1758282 ] complex missing __coerce__ + - [ 1777684 ] int and long types are missing __coerce__ + - [ 1785415 ] patch for : [ 1777684 ] int and long types are missing __coe + - [ 1514533 ] PyComplex in branch 2.3 + - [ 1783088 ] patch for :[ 1758282 ] complex missing __coerce__ + - [ 1758284 ] Complex parses complex('1' * 500) as (Infinity+0j) + - [ 1779428 ] patch for : [ 1758284 ] Complex parses complex('1' * 500) as + - [ 1671213 ] pickle/cPickle of Sets bug + - [ 1019 ] Can't change new-style class __name__ + - [ 1013 ] jython crash with command: threading.local() + - [ 1009 ] Patch to add 'at' to the repr string. + - [ 1005 ] UDP Socket implicit create and unbound socket timeout + - [ 1755346 ] imp missing lock_help + - [ 1758322 ] List mutation during sort doesn't throw a ValueError + - [ 1006 ] __import__ fromlist doesn't get processed + - [ 1782548 ] UDP send blocks with reader thread present + - [ 1895736 ] cleanup os.environ + - [ 1717491 ] os.path.islink incompletely implemented + - [ 1718450 ] Patch for os.path.islink bug 1717491 + - [ 1718975 ] Patch for os.path.normcase bug 1648449 + - [ 1648449 ] os.path.normcase broken in Windows + - [ 1814527 ] patch for [1803425], [1758322], [1785366] and upgraded sort + - [ 1861985 ] extending java classes from python code fails + - [ 1871739 ] fix for Import Error statement to match CPython + - [ 1870039 ] Debugging facility not behaving correctly with threads + - [ 1757127 ] Jython hangs under PyDev debugger + - [ 1839038 ] operations returning bools still return 1/0s + - [ 1861973 ] importing modules from class broken + - [ 1861974 ] patch for [1861973]. problems loading $py.class files + - [ 1850722 ] socket.py - ClientCookie and ClientForm + - [ 1482645 ] More OS recognition + - [ 1509095 ] Can't open midi sequencer + - [ 1850207 ] socket._fileobject - AttributeError: 'module' object has no + - [ 1816103 ] org.python.core.PyDictionary should implement java.util.Map + - [ 1721204 ] there is no threading.local() + - [ 1841639 ] Filecmp module is not in jython + - [ 1842984 ] Py.tojava(PyObject, Class) incorrectly marked deprecated + - [ 1841445 ] NPE in PythonInterpreter.get(String name, Class javaclass) + - [ 481404 ] CR removed on reading text on unix + - [ 1159156 ] codec.open() does not work with different systemstates + - [ 1261231 ] JButton('\u0F00') not working + - [ 1674190 ] exec() destroys multibyte string + - [ 1599900 ] Incorrect usage of String.getBytes() + - [ 1611604 ] PyFile hand-edited code + - [ 1839871 ] dict shouldn't call __setitem__ to initialise + - [ 1816134 ] Issue with Key Comparison in Dicts + - [ 1818353 ] sliceLength of PySequence returns 0 when step is sys.maxint + - [ 1791931 ] slice should be a type + - [ 1812122 ] NullPointerException when rethrowing an exception + - [ 1814678 ] Lack of some public functions' names in __all__ (javaos.py) + - [ 1796415 ] javaos.py missing removedirs function + - [ 1796425 ] javaos.py missing renames function. + - [ 1838358 ] Improve Resolution in time.clock() + - [ 1818393 ] why using Deprecated method in PyString? + - [ 1783692 ] Implementation of tempfile with secure files + - [ 1755344 ] tempfile missing mkdtemp + - [ 1817908 ] Broken link for corner icon in html documentation + - [ 1831710 ] PyFileCloser throws NullPointerException on shutdown + - [ 1744567 ] Simultaneous read & write on socket FileWrapper causes hang + - [ 1806980 ] os.path.join ignores empty string + - [ 1812913 ] File read converts \r to \n + - [ 1781500 ] Metaclasses don't get passed a '__module__' in attrs + - [ 1801802 ] JavaImportHelper not thread safe + - [ 1800378 ] object.__unicode__ should it exist? + - [ 1768982 ] sys.exc_clear is missing + - [ 1735774 ] Redirecting stdout/err with os.popen fails if cmd is unicode + - [ 1763263 ] os.utime(path, None) doesn't work (incl. a patch) + - [ 1758904 ] I added doc strings for functions in os module (javaos.py). + - [ 1768074 ] str.replace doesn't handle an empty string to be replaced + - [ 1799328 ] Unicode string interpolation doesn't work + - [ 1773865 ] Patch for [1768990] pickle fails on subclasses + - [ 1768990 ] pickle fails on subclasses of builtin types + - [ 1782493 ] On cli $ ./jython --version missing java version number + - [ 1783153 ] Patch: compatibility with Java 1.3 for Jython 2.2 + - [ 1755361 ] file missing 'U' universal newline mode + - [ 1782856 ] Error in zxJDBC.Timestamp() + - [ 1767194 ] Wrong namespace in xmllib in 2.2rc3 (patch included) + - [ 1783803 ] patch for bug [1775893] :in keyword + - [ 1775893 ] in keyword does not use dict.has_key() + - [ 1783960 ] can not exclude parts from installation + - [ 1785638 ] ImportError from zip without source + - [ 1783554 ] CPython compatible zipimporter + - [ 1775078 ] Fix binary operations on str/unicode/lists/tuples + - [ 1781556 ] Support list.extend(iterator), and other sequence fixes + - [ 1784564 ] Add PyLong.asInt + - [ 1768984 ] sys.builtin_module_names is missing + - [ 1768988 ] isinstance, issubclass allow a StackOverflow + - [ 1291509 ] cPickling bug + - [ 1758315 ] org.python.modules.operator lacks is and is_not functions + - [ 1758312 ] date and time objects fail to pickle + - [ 1758317 ] bool objects fail to pickle Incompatible Changes - The python.prepath property has been removed; use python.path instead. @@ -10,10 +295,14 @@ Collection instead of a PyList - The -E codec command line option (use a different codec when reading from the console) has been changed to -C codec - + - import of Python modules does not imply the import of child modules, though + import of Java packages still does, see email thread with Guido van Rossum, + Samuele Pedroni, and Frank Wierzbicki: + http://www.mailinglistarchive.com/pyt...@py.../msg07683.html + New Features - PyDictionary now implements Map so it may be passed to any Java function expecting a Map. - + - modjy integrated into core Ported Modules - collections - filecmp Modified: trunk/jython/README.txt =================================================================== --- trunk/jython/README.txt 2009-03-07 15:35:39 UTC (rev 6080) +++ trunk/jython/README.txt 2009-03-07 15:57:43 UTC (rev 6081) @@ -1,8 +1,9 @@ -Welcome to Jython 2.5b1 +Welcome to Jython 2.5b2 ======================= -This is the second beta of the 2.5 version of Jython. It -contains most of the new features for the 2.5 release. +This is the third beta of the 2.5 version of Jython. It +contains all of the new features for the 2.5 release and represents a feature +freeze. The release was compiled on Mac OS X with JDK 5 and requires JDK 5 to run. Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-03-07 15:35:39 UTC (rev 6080) +++ trunk/jython/build.xml 2009-03-07 15:57:43 UTC (rev 6081) @@ -188,13 +188,13 @@ <property name="PY_RELEASE_LEVEL_SNAPSHOT" value="170"/> <!-- 0xAA --> <!-- The current version info --> - <property name="jython.version" value="2.5b1+"/> - <property name="jython.version.noplus" value="2.5b1"/> + <property name="jython.version" value="2.5b2+"/> + <property name="jython.version.noplus" value="2.5b2"/> <property name="jython.major_version" value="2"/> <property name="jython.minor_version" value="5"/> <property name="jython.micro_version" value="0"/> <property name="jython.release_level" value="${PY_RELEASE_LEVEL_BETA}"/> - <property name="jython.release_serial" value="0"/> + <property name="jython.release_serial" value="2"/> <condition property="do.snapshot.build"> <isset property="snapshot.revision" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-03-10 18:47:46
|
Revision: 6087 http://jython.svn.sourceforge.net/jython/?rev=6087&view=rev Author: fwierzbicki Date: 2009-03-10 18:47:33 +0000 (Tue, 10 Mar 2009) Log Message: ----------- Unit tests and fix for http://bugs.jython.org/issue1126 "ImportError raised for Java subpackages import". Thanks to boisgera for the report and for the unit testing code. Modified Paths: -------------- trunk/jython/Lib/test/test_classpathimporter.py trunk/jython/NEWS trunk/jython/src/org/python/core/imp.java Added Paths: ----------- trunk/jython/Lib/test/bug1126/ trunk/jython/Lib/test/bug1126/bug1126.jar Added: trunk/jython/Lib/test/bug1126/bug1126.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/Lib/test/bug1126/bug1126.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/jython/Lib/test/test_classpathimporter.py =================================================================== --- trunk/jython/Lib/test/test_classpathimporter.py 2009-03-10 17:29:42 UTC (rev 6086) +++ trunk/jython/Lib/test/test_classpathimporter.py 2009-03-10 18:47:33 UTC (rev 6087) @@ -48,6 +48,12 @@ sys.path.append("Lib/test/bug1239.jar") import org.test403javapackage.test403 + # different from test_bug1239 in that only a Java package is imported, not + # a Java class. I'd also like to get rid of this checked in test jar. + def test_bug1126(self): + sys.path.append("Lib/test/bug1126/bug1126.jar") + import org.subpackage + def test_main(): test_support.run_unittest(ClasspathImporterTestCase) Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2009-03-10 17:29:42 UTC (rev 6086) +++ trunk/jython/NEWS 2009-03-10 18:47:33 UTC (rev 6087) @@ -2,6 +2,7 @@ Jython 2.5 Bugs fixed (new numbering due to move to Roundup) + - [ 1126 ] ImportError raised for Java subpackages import - [ 1111 ] keyword arguments not supported on __import__ - [ 1567212 ] Jython $py.class bytecode doesn't include the .py's mtime - [ 1024 ] Jython $py.class bytecode doesn't include the .py's mtime Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2009-03-10 17:29:42 UTC (rev 6086) +++ trunk/jython/src/org/python/core/imp.java 2009-03-10 18:47:33 UTC (rev 6087) @@ -635,9 +635,20 @@ } else { name = dottedName.substring(last_dot, dot); } + PyJavaPackage jpkg = null; + if (mod instanceof PyJavaPackage) { + jpkg = (PyJavaPackage)mod; + } + mod = import_next(mod, parentNameBuffer, name, fullName, fromlist); + if (jpkg != null && (mod == null || mod == Py.None)) { + // try again -- under certain circumstances a PyJavaPackage may + // have been added as a side effect of the last import_next + // attempt. see Lib/test_classpathimport.py#test_bug1126 + mod = import_next(jpkg, parentNameBuffer, name, fullName, fromlist); + } if (mod == null || mod == Py.None) { - throw Py.ImportError("No module named " + name); + throw Py.ImportError("No module named " + name); } last_dot = dot + 1; } while (dot != -1); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |