embedding Jython

bleary

Member
It's possible:

b6atqb.jpg


I'm still not sure how to get it to build automatically, and I'm not sure that the ultimate binary would be distributable. Which is funny, because I'm a lawyer, not a programmer.

Can anyone think of a good use for it?
 

slyz

Developer
I definitively can (if I understand correctly what this does). This sounds like it would be great for exploring Mafia's internals and debugging or understanding things.

How do you do this? :)
 

bleary

Member
I made a self-contained jython.jar using the jython installer. I made sure that it ended up in the same place as my kolmafia jar, and that my application bundle referenced the jython jar as well as the kolmafia jar. I'm not exactly sure how CLASSPATH works.

I also put the jython jar into the build area for kolmafia, and modified build.xml so it was in the classpath.

I also downloaded and extracted jythonconsole (http://code.google.com/p/jythonconsole/). Note that I haven't figured out how to stuff it into the Kolmafia distribution yet.

Code:
--- build.xml   (revision 10057)
+++ build.xml   (working copy)
@@ -184,7 +184,7 @@
                        source="1.4"
                        srcdir="${src}"
                        destdir="${build}"
-                       classpath="${build}"
+                       classpath="${build}:${build}/jython.jar"
                        failonerror="false"
                        debug="on"
                        debuglevel="lines,vars,source"

I added a new file: src/net/sourceforge/kolmafia/swingui/JythonConsoleFrame.java

(I haven't figured out how to deal with the absolute path for jython-console yet, so that reference would need to be changed.)

Code:
package net.sourceforge.kolmafia.swingui;

import java.awt.BorderLayout;


import javax.swing.JTabbedPane;

import net.sourceforge.kolmafia.KoLConstants;
import net.sourceforge.kolmafia.KoLmafia;
import net.sourceforge.kolmafia.KoLmafiaCLI;
import net.sourceforge.kolmafia.StaticEntity;


import net.sourceforge.kolmafia.utilities.PauseObject;

import org.python.core.PySystemState;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;


public class JythonConsoleFrame
        extends GenericFrame
{
        private static final PauseObject pauser = new PauseObject();
    private static PythonInterpreter interpreter;


        public JythonConsoleFrame()
        {
                super( "Jython Console" );


                PySystemState.initialize();
                this.interpreter  = new PythonInterpreter();
                //this.framePanel.add( commandPanel, BorderLayout.CENTER );
                this.interpreter.exec("import sys");    
                // you can pass the python.path to java to avoid hardcoding this
                // java -Dpython.path=/path/to/jythonconsole-0.0.6 EmbedExample
                this.interpreter.exec("sys.path.append(r'/Users/tew/KoL/projects/pykolmafia/jythonconsole-0.0.7/')");
                this.interpreter.set("frame",this);
                this.interpreter.exec("from console import Console,JScrollPane");
                this.interpreter.exec("console = Console(None)");
                this.interpreter.exec("frame.getContentPane().add(JScrollPane(console.text_pane))");

        }

        public JTabbedPane getTabbedPane()
        {
                return null;
        }

        public boolean shouldAddStatusBar()
        {
                return false;
        }

        public boolean useSidePane()
        {
                return true;
        }

        public void requestFocus()
        {
                super.requestFocus();
                //this.commandPanel.requestFocus();
        }

        public boolean requestFocus( boolean temporary )
        {
                return super.requestFocus( temporary );
                //return this.commandPanel.requestFocus( temporary );
        }

        public boolean requestFocusInWindow()
        {
                return super.requestFocusInWindow();
                //return this.commandPanel.requestFocusInWindow();
        }

        public boolean requestFocusInWindow( boolean temporary )
        {
                return super.requestFocusInWindow( temporary );
                //return this.commandPanel.requestFocusInWindow( temporary );
        }

        public static final boolean hasQueuedCommands()
        {
            //return !JythonConsoleFrame.commandQueue.isEmpty();
            return false;
        }


}

A few diffs to existing files:

Code:
Index: src/net/sourceforge/kolmafia/KoLmafiaGUI.java
===================================================================
--- src/net/sourceforge/kolmafia/KoLmafiaGUI.java       (revision 10057)
+++ src/net/sourceforge/kolmafia/KoLmafiaGUI.java       (working copy)
@@ -82,6 +82,9 @@
 import net.sourceforge.kolmafia.webui.RelayServer;
 import tab.CloseTabbedPane;
 
+import net.sourceforge.kolmafia.swingui.JythonConsoleFrame;
+
+
 public class KoLmafiaGUI
        extends KoLmafia
 {

Index: src/net/sourceforge/kolmafia/KoLDesktop.java
===================================================================
--- src/net/sourceforge/kolmafia/KoLDesktop.java        (revision 10057)
+++ src/net/sourceforge/kolmafia/KoLDesktop.java        (working copy)
@@ -421,6 +421,7 @@
                toolbarPanel.add( new RelayBrowserButton( "Load in Web Browser", "browser.gif", null ) );
 
                toolbarPanel.add( new DisplayFrameButton( "Graphical CLI", "command.gif", "CommandDisplayFrame" ) );
+               toolbarPanel.add( new DisplayFrameButton( "Jython Console", "command.gif", "JythonConsoleFrame" ) );
 
                toolbarPanel.add( Box.createHorizontalStrut( 10 ) );
 
Index: src/net/sourceforge/kolmafia/KoLConstants.java
===================================================================
--- src/net/sourceforge/kolmafia/KoLConstants.java      (revision 10057)
+++ src/net/sourceforge/kolmafia/KoLConstants.java      (working copy)
@@ -262,6 +262,10 @@
                        "OptionsFrame"
                },
                {
+                       "Jython Console",
+                       "JythonConsoleFrame"
+               },
+               {
                        "Modifier Maximizer",
                        "MaximizerFrame"
                }

And, that's it. It oughta build, but there might need to be some additional kludging to make sure that your running jar is set up properly to find the jython.jar.

The jython interpreter doesn't run in its own thread (not sure how to do that) so any long-running loops will block all of mafia. Maybe that's desirable behavior.
 

slyz

Developer
It's a way to expose Mafia's internals (right?), so it's not of much use to ASH scripters.
 

slyz

Developer
I managed to add jython.jar to CLASSPATH by putting it in its own folder in /utils and changing the line in build.xml to
Code:
classpath="${build}:${util}/jython/jython.jar"
When I put it in /build, it was erased each time I ran ant daily.

Now I have this error when I try to start the Jython tab in the GUI:
Code:
net.sourceforge.kolmafia.swingui.JythonConsoleFrame could not be loaded
along with a debug log blaming the error on
Code:
java.lang.ClassNotFoundException: org.python.core.PySystemState

The only difference with what you posted is the path to jythonconsole:
PHP:
this.interpreter.exec("sys.path.append(r'D:/dloads/KoLMafiaUpdates/jython/jythonconsole-0.0.7/')");
That's on windows, maybe the 'r' isn't needed or something.

I also tried doing what the comment suggests:
PHP:
// you can pass the python.path to java to avoid hardcoding this
// java -Dpython.path=/path/to/jythonconsole-0.0.6 EmbedExample
and commenting the sys.path.append() line, but no dice.

I would like to try this out, but I feel like I wandered over to the deep end of the pool without my water wings.
 
Last edited:

bleary

Member
slyz, that sounds to me like your kolmafia can't find the jython.jar at runtime. kolmafia for windows gets packaged up into an exe by jsmooth, which appears to lack the ability to stuff multiple jars into the executable. I guess you need to figure out how to make jsmooth (in util/windows) set the classpath properly to reference a jython.jar that's not stored inside the executable, possibly by adding to util/windows/build.jsmooth line like:
Code:
<classPath>..\path\to\jython.jar</classPath>
 

bleary

Member
Awesomesauce, and congrats, but what would the practical benefits of this be to scripters?

Well, if at some point, kolmafia could be taught to run python scripts alongside ash scripts, scripts could be written in python (which would give all of the advantages/disadvantages of a full-fledged scripting language, including its standard libraries), with full access to all of the mafia internals. So, for instance, a script could modify the GUI or create new GUI windows.

slyz pointed out that the interactive console allows a developer to interrogate mafia's internal state pretty effectively. Which I guess could also be useful.
 
Top