Replacing JythonC in Jython 2.5

| No Comments

I heard, on the jython podcast's latest episode, of a replacement for jythonc. After the flip, I've edited Dan Cheahs jythonc replacement, compile.java, to add per file output and use the system-wide, platform-independant temporary directory, as denoted by the java.io.tmpdir property.

Reblog this post [with Zemanta]
import java.io.File;
import java.util.Properties;
import java.util.Set;
import java.util.HashSet;

import org.python.core.PyException;
import org.python.core.PySystemState;
import org.python.core.imp;
import org.python.modules._py_compile;

/**
 * Compiles all python files in a directory to bytecode, and writes them to another directory,
 * possibly the same one.
 */
public class compile {

    class BuildException extends RuntimeException {
        public BuildException(String message) {
        }
    }
    
    public void log(String message) { // use java.util.logging?
        System.out.println(message);
    }
    
    public compile() {
    }

    public void process(Set toCompile) throws BuildException {
        String destDir = System.getProperty("java.io.tmpdir");

        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('.', File.separatorChar);
            if (src.getName().endsWith("__init__.py")) {
                compiledFilePath += File.separator+"__init__";
            }
            File compiled = new File(destDir, compiledFilePath + "$py.class");
            compile(src, compiled, name);
	    log(name+" => "+destDir+compiled.getName());
        }
    }
    
    /**
     * Compiles the python file src to bytecode filling in moduleName as
     * its name, and stores it in compiled. This is called by process for every file
     * that's compiled, so subclasses can override this method to affect or track the compilation.
     */
    protected void compile(File src, File compiled, String moduleName) {
        byte[] bytes;
        try {
            bytes = imp.compileSource(moduleName, 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";
    }
    
    public static void main(String[] args) {
        String filename = args[0];
	
        Set fileSet = new HashSet();
        
        File file = new File(filename);
        fileSet.add(file);
        
        compile c = new compile();
        c.process(fileSet);
    }

}

Leave a comment

Bookmark and Share

Connect with me


qrcode
Add me on AOL
Hasan Diwan

Follow me on Twitter
Ring me at +1 6502844111
See my photos
How about some analytics?

Twitter

Archives

Creative Commons License
This blog is licensed under a Creative Commons License.