source: pythonadapter/src/main/java/geniusweb/pythonadapter/PythonPartyAdapter.java@ 9

Last change on this file since 9 was 9, checked in by bart, 5 years ago

Release 1.1.0

File size: 3.8 KB
Line 
1package geniusweb.pythonadapter;
2
3import org.python.core.Py;
4import org.python.core.PyObject;
5import org.python.core.PySystemState;
6import org.python.util.PythonInterpreter;
7
8import geniusweb.actions.Action;
9import geniusweb.connection.ConnectionEnd;
10import geniusweb.party.Capabilities;
11import geniusweb.party.DefaultParty;
12import geniusweb.party.Party;
13import geniusweb.party.inform.Inform;
14import tudelft.utilities.listener.Listener;
15
16/**
17 * An adapter that allows you to put a python-based Party into a jar file and
18 * use it with Genius2. This adapter supports the jython dialect. The reason
19 * this adapter is needed is that you can not directly use the .py file in java,
20 * we have to load a python interpreter and connect it to your file. *
21 * <h1>Usage</h1>
22 *
23 * <ul>
24 * <li>Place an implementation of this class (PythonPartyAdapter) inside your
25 * jar.
26 * <li>Implement {@link #getPythonClass()} so that it returns the proper name of
27 * your implementation.
28 * <li>Point to this implementation as the mainclass in the META-INF file. Check
29 * the RandomPyParty example on how to do this from Maven.
30 * <li>Ensure your Python file(s) get in the root of the jar. Eg, put them in
31 * resources/ or similar inside your maven project if you use maven.
32 * <li>Add more dependencies as needed, eg to access the Bid class or for
33 * deserializing.
34 * <li>Make sure you use the jar-with-dependencies in the parties server, as
35 * that includes jython.
36 * </ul>
37 *
38 * <p>
39 * <h1>Working principle</h1>
40 *
41 * The created jar file contains a full python interpreter plus some glue code.
42 * The glue code runs your party inside the python interpreter and routes the
43 * calls through the Geniuseb java structures.
44 */
45public abstract class PythonPartyAdapter implements Party, Listener<Inform> {
46
47 private final PythonInterpreter interpreter = new PythonInterpreter();
48 private final DefaultParty pyparty;
49
50 public PythonPartyAdapter() {
51 /**
52 * Normally Party does not have a constructor. However this is a special
53 * case where we need to initialize Python and connect the python class.
54 */
55 interpreter.exec("import sys");
56 addPath("");
57 System.out.println("code is at " + getClass().getProtectionDomain()
58 .getCodeSource().getLocation().getPath());
59 // point to sources. Should include all dependencies.
60 // should work both in Eclipse and when using the compiled jar.
61 addPath(getClass().getProtectionDomain().getCodeSource().getLocation()
62 .getPath());
63 PySystemState state = new PySystemState();
64 PyObject importer = state.getBuiltins()
65 .__getitem__(Py.newString("__import__"));
66 PyObject module = importer.__call__(Py.newString(getPythonClass()));
67 PyObject klass = module.__getattr__(getPythonClass());
68 pyparty = (DefaultParty) klass.__call__()
69 .__tojava__(DefaultParty.class);
70 }
71
72 /**
73 * @return the class/modulename of both your python module filename (eg,
74 * X.py) and your python class (eg class X) inside that file that
75 * implements {@link DefaultParty}. This file must be in the root of
76 * the jar file/working directory. The name is without an extension.
77 */
78 abstract public String getPythonClass();
79
80 @Override
81 public Capabilities getCapabilities() {
82 return pyparty.getCapabilities();
83 }
84
85 @Override
86 public String getDescription() {
87 return pyparty.getDescription();
88 }
89
90 @Override
91 public void notifyChange(Inform data) {
92 pyparty.notifyChange(data);
93 }
94
95 @Override
96 public void disconnect() {
97 pyparty.disconnect();
98 }
99
100 @Override
101 public void terminate() {
102 pyparty.terminate();
103 }
104
105 @Override
106 public void connect(ConnectionEnd<Inform, Action> connection) {
107 pyparty.connect(connection);
108 }
109
110 private void addPath(String relpath) {
111 String path = System.getProperty("user.dir") + "/" + relpath + "/";
112
113 System.out.println("adding python path " + path);
114 interpreter.exec("sys.path.insert(0, '" + path + "')");
115
116 }
117
118}
Note: See TracBrowser for help on using the repository browser.