GP-4659: Renaming "Python" module to "Jython"

This commit is contained in:
Ryan Kurtz 2024-06-03 11:29:56 -04:00
parent 9840eee937
commit fb1f725f5b
46 changed files with 285 additions and 284 deletions

View file

@ -21,7 +21,7 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
apply from: "$rootProject.projectDir/gradle/javadoc.gradle" apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
apply plugin: 'eclipse' apply plugin: 'eclipse'
eclipse.project.name = 'Features Python' eclipse.project.name = 'Features Jython'
def JYTHON = "org.python:jython-standalone:2.7.3" def JYTHON = "org.python:jython-standalone:2.7.3"
@ -51,15 +51,15 @@ task jythonUnpack(type: Copy) {
destinationDir file("build/data/${JYTHON_DIR}") destinationDir file("build/data/${JYTHON_DIR}")
} }
task pythonSrcCopy(type: Copy) { task jythonSrcCopy(type: Copy) {
description "Copy python-src directory (for Feature Python)" description "Copy jython-src directory (for Feature Jython)"
from(file("python-src")) from(file("jython-src"))
destinationDir file("build/data/python-src") destinationDir file("build/data/jython-src")
} }
// Ensure that Jython is usable in development xx // Ensure that Jython is usable in development xx
rootProject.prepDev.dependsOn jythonUnpack rootProject.prepDev.dependsOn jythonUnpack
jar.dependsOn jythonUnpack jar.dependsOn jythonUnpack
jar.dependsOn pythonSrcCopy jar.dependsOn jythonSrcCopy

View file

@ -2,7 +2,7 @@
##MODULE IP: Jython License ##MODULE IP: Jython License
##MODULE IP: LGPL 2.1 ##MODULE IP: LGPL 2.1
Module.manifest||GHIDRA||||END| Module.manifest||GHIDRA||||END|
data/python.theme.properties||GHIDRA||||END| data/jython.theme.properties||GHIDRA||||END|
src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END|
src/main/help/help/topics/Python/interpreter.html||GHIDRA||||END| src/main/help/help/topics/Jython/interpreter.html||GHIDRA||||END|
src/main/resources/images/python.png||GHIDRA||||END| src/main/resources/images/python.png||GHIDRA||||END|

View file

@ -0,0 +1,21 @@
[Defaults]
color.fg.plugin.jython.syntax.class = color.palette.blue
color.fg.plugin.jython.syntax.code = color.palette.darkgreen
color.fg.plugin.jython.syntax.function = color.palette.green
color.fg.plugin.jython.syntax.instance = color.palette.purple
color.fg.plugin.jython.syntax.map = color.palette.steelblue
color.fg.plugin.jython.syntax.method = color.palette.teal
color.fg.plugin.jython.syntax.null = color.palette.red
color.fg.plugin.jython.syntax.number = color.palette.darkgray
color.fg.plugin.jython.syntax.package = color.palette.darkred
color.fg.plugin.jython.syntax.sequence = color.palette.saddlebrown
color.fg.plugin.jython.syntax.special = color.palette.darkgreen
icon.plugin.jython = python.png
[Dark Defaults]

View file

@ -16,7 +16,7 @@ import sys
import tokenize import tokenize
import types import types
import __main__ import __main__
from ghidra.python import PythonCodeCompletionFactory from ghidra.jython import JythonCodeCompletionFactory
import java # needed for java.lang.Class import java # needed for java.lang.Class
try: try:
@ -72,7 +72,7 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1,
pyObj = getattr(object, attribute) pyObj = getattr(object, attribute)
else: else:
pyObj = locals[attribute] pyObj = locals[attribute]
completion_list.append(PythonCodeCompletionFactory. completion_list.append(JythonCodeCompletionFactory.
newCodeCompletion(attribute, newCodeCompletion(attribute,
attribute, attribute,
pyObj, pyObj,

View file

@ -8,7 +8,7 @@ import string
import __builtin__ import __builtin__
import java # needed for java.lang.Class import java # needed for java.lang.Class
import org # for org.python.core import org # for org.python.core
import ghidra # for PythonCodeCompletionFactory import ghidra # for JythonCodeCompletionFactory
__author__ = "Don Coleman <dcoleman@chariotsolutions.com>" __author__ = "Don Coleman <dcoleman@chariotsolutions.com>"

View file

@ -3,7 +3,7 @@
<tocroot> <tocroot>
<tocref id="Ghidra Functionality"> <tocref id="Ghidra Functionality">
<tocref id="Scripting"> <tocref id="Scripting">
<tocdef id="Python Interpreter" sortgroup="z" text="Python Interpreter" target="help/topics/Python/interpreter.html" /> <tocdef id="Jython Interpreter" sortgroup="z" text="Jython Interpreter" target="help/topics/Jython/interpreter.html" />
</tocref> </tocref>
</tocref> </tocref>
</tocroot> </tocroot>

View file

@ -2,15 +2,15 @@
<HTML> <HTML>
<HEAD> <HEAD>
<TITLE>Python Interpreter</TITLE> <TITLE>Jython Interpreter</TITLE>
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css"> <LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
</HEAD> </HEAD>
<BODY lang="EN-US"> <BODY lang="EN-US">
<H1><A name="Python"></A>Python Interpreter</H1> <H1><A name="Jython"></A>Jython Interpreter</H1>
<P> <P>
The Ghidra <I>Python Interpreter</I> provides a full general-purpose Python interactive shell The Ghidra <I>Jython Interpreter</I> provides a full general-purpose Jython interactive shell
and allows you to interact with your current Ghidra session by exposing Ghidra's powerful Java and allows you to interact with your current Ghidra session by exposing Ghidra's powerful Java
API through the magic of Jython. API through the magic of Jython.
</P> </P>
@ -18,7 +18,7 @@
<H2>Environment</H2> <H2>Environment</H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<P> <P>
The Ghidra <I>Python Interpreter</I> is configured to run in a similar context as a Ghidra The Ghidra <I>Jython Interpreter</I> is configured to run in a similar context as a Ghidra
script. Therefore, you immediately have access to variables such as <TT>currentProgram</TT>, script. Therefore, you immediately have access to variables such as <TT>currentProgram</TT>,
<TT>currentSelection</TT>, <TT>currentAddress</TT>, etc without needing to import them. <TT>currentSelection</TT>, <TT>currentAddress</TT>, etc without needing to import them.
These variables exist as Java objects behind the scenes, but Jython allows you to interact with These variables exist as Java objects behind the scenes, but Jython allows you to interact with
@ -48,7 +48,7 @@
hierarchy, so nothing has to be explicitly imported before they can be used. However, because hierarchy, so nothing has to be explicitly imported before they can be used. However, because
the <TT>DataTypeSelectionDialog</TT> class and <TT>AllowedDataType</TT> enum reside in the <TT>DataTypeSelectionDialog</TT> class and <TT>AllowedDataType</TT> enum reside in
different packages, they must be explicitly imported. Failure to do so will result in a different packages, they must be explicitly imported. Failure to do so will result in a
Python <TT><FONT COLOR="RED">NameError</FONT></TT>. Jython <TT><FONT COLOR="RED">NameError</FONT></TT>.
</P> </P>
</BLOCKQUOTE> </BLOCKQUOTE>
@ -78,7 +78,7 @@
<H2>Keybindings</H2> <H2>Keybindings</H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<P> <P>
The Ghidra <I>Python Interpreter</I> supports the following hard-coded keybindings: The Ghidra <I>Jython Interpreter</I> supports the following hard-coded keybindings:
<UL> <UL>
<LI><B>(up):</B>&nbsp;&nbsp;Move backward in command stack</LI> <LI><B>(up):</B>&nbsp;&nbsp;Move backward in command stack</LI>
<LI><B>(down):</B>&nbsp;&nbsp;Move forward in command stack</LI> <LI><B>(down):</B>&nbsp;&nbsp;Move forward in command stack</LI>
@ -100,7 +100,7 @@
<H2>Copy/Paste</H2> <H2>Copy/Paste</H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<P> <P>
Copy and paste from within the Ghidra <I>Python Interpreter</I> should work as expected for Copy and paste from within the Ghidra <I>Jython Interpreter</I> should work as expected for
your given environment: your given environment:
<UL> <UL>
<LI><B>Windows:</B>&nbsp;&nbsp;CTRL+C / CTRL+V</LI> <LI><B>Windows:</B>&nbsp;&nbsp;CTRL+C / CTRL+V</LI>
@ -113,7 +113,7 @@
<H2>API Documentation</H2> <H2>API Documentation</H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<P> <P>
The built-in <TT>help()</TT> Python function has been altered by the Ghidra <I>Python Interpreter</I> The built-in <TT>help()</TT> Jython function has been altered by the Ghidra <I>Jython Interpreter</I>
to add support for displaying Ghidra's Javadoc (where available) for a given Ghidra class, method, to add support for displaying Ghidra's Javadoc (where available) for a given Ghidra class, method,
or variable. For example, to see Ghidra's Javadoc on the <TT>state</TT> variable, simply do: or variable. For example, to see Ghidra's Javadoc on the <TT>state</TT> variable, simply do:
<PRE> <PRE>
@ -147,7 +147,7 @@
</P> </P>
<P> <P>
<B>Note:</B> It may be necessary to import a Ghidra class before calling the built-in <TT>help()</TT> <B>Note:</B> It may be necessary to import a Ghidra class before calling the built-in <TT>help()</TT>
Python function on it. Failure to do so will result in a Python <TT><FONT COLOR="RED">NameError</FONT></TT>. Jython function on it. Failure to do so will result in a Jython <TT><FONT COLOR="RED">NameError</FONT></TT>.
</P> </P>
</BLOCKQUOTE> </BLOCKQUOTE>
@ -160,7 +160,7 @@
</P> </P>
</BLOCKQUOTE> </BLOCKQUOTE>
<P align="left" class="providedbyplugin">Provided by: <I>PythonPlugin</I></P> <P align="left" class="providedbyplugin">Provided by: <I>JythonPlugin</I></P>
<P>&nbsp;</P> <P>&nbsp;</P>
<BR> <BR>

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -41,7 +41,7 @@ import util.CollectionUtils;
* There is no longer a way to reset an interpreter...it was too complicated to get right. * There is no longer a way to reset an interpreter...it was too complicated to get right.
* Instead, you should {@link #cleanup()} your old interpreter and make a new one. * Instead, you should {@link #cleanup()} your old interpreter and make a new one.
*/ */
public class GhidraPythonInterpreter extends InteractiveInterpreter { public class GhidraJythonInterpreter extends InteractiveInterpreter {
private static boolean pythonInitialized; private static boolean pythonInitialized;
private static List<PyString> defaultPythonPath; private static List<PyString> defaultPythonPath;
@ -58,23 +58,23 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
* *
* @return A new GhidraPythonInterpreter. Could be null if it failed to be created. * @return A new GhidraPythonInterpreter. Could be null if it failed to be created.
*/ */
public static GhidraPythonInterpreter get() { public static GhidraJythonInterpreter get() {
// Initialize the python environment if necessary. Only needs to happen once. // Initialize the python environment if necessary. Only needs to happen once.
if (!pythonInitialized) { if (!pythonInitialized) {
try { try {
// Setup python home directory // Setup python home directory
PythonUtils.setupPythonHomeDir(); JythonUtils.setupJythonHomeDir();
// Setup python cache directory // Setup python cache directory
PythonUtils.setupPythonCacheDir(TaskMonitor.DUMMY); JythonUtils.setupJythonCacheDir(TaskMonitor.DUMMY);
// Indicate that we've initialized the python environment, which should // Indicate that we've initialized the python environment, which should
// only happen once. // only happen once.
pythonInitialized = true; pythonInitialized = true;
} }
catch (Exception e) { catch (Exception e) {
Msg.showError(GhidraPythonInterpreter.class, null, "Python error", Msg.showError(GhidraJythonInterpreter.class, null, "Python error",
"Problem getting Ghirda Python interpreter", e); "Problem getting Ghirda Python interpreter", e);
return null; return null;
} }
@ -86,7 +86,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
state.ps2 = new PyString("... "); state.ps2 = new PyString("... ");
// Return a new instance of our interpreter // Return a new instance of our interpreter
return new GhidraPythonInterpreter(state); return new GhidraJythonInterpreter(state);
} }
/** /**
@ -94,7 +94,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
* *
* @param state The initial system state of the interpreter. * @param state The initial system state of the interpreter.
*/ */
private GhidraPythonInterpreter(PySystemState state) { private GhidraJythonInterpreter(PySystemState state) {
super(null, state); super(null, state);
// Store the default python path in case we need to reset it later. // Store the default python path in case we need to reset it later.
@ -158,7 +158,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
* @throws PyException if an unhandled exception occurred while executing the line of python * @throws PyException if an unhandled exception occurred while executing the line of python
* @throws IllegalStateException if this interpreter has been cleaned up. * @throws IllegalStateException if this interpreter has been cleaned up.
*/ */
public synchronized boolean push(String line, PythonScript script) public synchronized boolean push(String line, JythonScript script)
throws PyException, IllegalStateException { throws PyException, IllegalStateException {
if (cleanedUp) { if (cleanedUp) {
@ -198,7 +198,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
* @param script A PythonScript from which we load state (or null). * @param script A PythonScript from which we load state (or null).
* @throws IllegalStateException if this interpreter has been cleaned up. * @throws IllegalStateException if this interpreter has been cleaned up.
*/ */
public synchronized void execFile(ResourceFile file, PythonScript script) public synchronized void execFile(ResourceFile file, JythonScript script)
throws IllegalStateException { throws IllegalStateException {
if (cleanedUp) { if (cleanedUp) {
@ -332,7 +332,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
* *
* @param script The script whose class hierarchy is to be used for injection. * @param script The script whose class hierarchy is to be used for injection.
*/ */
void injectScriptHierarchy(PythonScript script) { void injectScriptHierarchy(JythonScript script) {
if (script == null) { if (script == null) {
return; return;
@ -447,7 +447,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
* @param includeBuiltins True if we should include python built-ins; otherwise, false. * @param includeBuiltins True if we should include python built-ins; otherwise, false.
* @param caretPos The position of the caret in the input string 'cmd' * @param caretPos The position of the caret in the input string 'cmd'
* @return A list of possible command completions. Could be empty if there aren't any. * @return A list of possible command completions. Could be empty if there aren't any.
* @see PythonPlugin#getCompletions * @see JythonPlugin#getCompletions
*/ */
List<CodeCompletion> getCommandCompletions(String cmd, boolean includeBuiltins, int caretPos) { List<CodeCompletion> getCommandCompletions(String cmd, boolean includeBuiltins, int caretPos) {
// At this point the caret is assumed to be positioned right after the value we need to // At this point the caret is assumed to be positioned right after the value we need to

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.awt.Color; import java.awt.Color;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -31,12 +31,12 @@ import ghidra.framework.options.Options;
import ghidra.util.Msg; import ghidra.util.Msg;
/** /**
* Generates CodeCompletions from Python objects. * Generates CodeCompletions from Jython objects.
* *
* *
* *
*/ */
public class PythonCodeCompletionFactory { public class JythonCodeCompletionFactory {
private static List<Class<?>> classes = new ArrayList<>(); private static List<Class<?>> classes = new ArrayList<>();
private static Map<Class<?>, Color> classToColorMap = new HashMap<>(); private static Map<Class<?>, Color> classToColorMap = new HashMap<>();
/* necessary because we only want to show the user the simple class name /* necessary because we only want to show the user the simple class name
@ -47,7 +47,7 @@ public class PythonCodeCompletionFactory {
private static Map<Class<?>, String> classDescription = new HashMap<>(); private static Map<Class<?>, String> classDescription = new HashMap<>();
public static final String COMPLETION_LABEL = "Code Completion Colors"; public static final String COMPLETION_LABEL = "Code Completion Colors";
/* package-level accessibility so that PythonPlugin can tell this is /* package-level accessibility so that JythonPlugin can tell this is
* our option * our option
*/ */
final static String INCLUDE_TYPES_LABEL = "Include type names in code completion popup?"; final static String INCLUDE_TYPES_LABEL = "Include type names in code completion popup?";
@ -59,19 +59,19 @@ public class PythonCodeCompletionFactory {
private static boolean includeTypes = INCLUDE_TYPES_DEFAULT; private static boolean includeTypes = INCLUDE_TYPES_DEFAULT;
//@formatter:off //@formatter:off
public static final Color NULL_COLOR = new GColor("color.fg.plugin.python.syntax.null"); public static final Color NULL_COLOR = new GColor("color.fg.plugin.jython.syntax.null");
public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.python.syntax.function"); public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.jython.syntax.function");
public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.python.syntax.package"); public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.jython.syntax.package");
public static final Color CLASS_COLOR = new GColor("color.fg.plugin.python.syntax.class"); public static final Color CLASS_COLOR = new GColor("color.fg.plugin.jython.syntax.class");
public static final Color METHOD_COLOR = new GColor("color.fg.plugin.python.syntax.method"); public static final Color METHOD_COLOR = new GColor("color.fg.plugin.jython.syntax.method");
/* anonymous code chunks */ /* anonymous code chunks */
public static final Color CODE_COLOR = new GColor("color.fg.plugin.python.syntax.code"); public static final Color CODE_COLOR = new GColor("color.fg.plugin.jython.syntax.code");
public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.python.syntax.instance"); public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.jython.syntax.instance");
public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.python.syntax.sequence"); public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.jython.syntax.sequence");
public static final Color MAP_COLOR = new GColor("color.fg.plugin.python.syntax.map"); public static final Color MAP_COLOR = new GColor("color.fg.plugin.jython.syntax.map");
public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.python.syntax.number"); public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.jython.syntax.number");
/* for weird Jython-specific stuff */ /* for weird Jython-specific stuff */
public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.python.syntax.special"); public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.jython.syntax.special");
//@formatter:on //@formatter:on
static { static {
@ -174,18 +174,18 @@ public class PythonCodeCompletionFactory {
classDescription.put(klass, description); classDescription.put(klass, description);
} }
catch (ClassNotFoundException cnfe) { catch (ClassNotFoundException cnfe) {
Msg.debug(PythonCodeCompletionFactory.class, "Unable to find class: " + className, Msg.debug(JythonCodeCompletionFactory.class, "Unable to find class: " + className,
cnfe); cnfe);
} }
} }
/** /**
* Creates a new CodeCompletion from the given Python objects. * Creates a new CodeCompletion from the given Jython objects.
* *
* @param description description of the new CodeCompletion * @param description description of the new CodeCompletion
* @param insertion what will be inserted to make the code complete * @param insertion what will be inserted to make the code complete
* @param pyObj a Python Object * @param pyObj a Jython Object
* @return A new CodeCompletion from the given Python objects. * @return A new CodeCompletion from the given Jython objects.
* @deprecated use {@link #newCodeCompletion(String, String, PyObject, String)} instead, * @deprecated use {@link #newCodeCompletion(String, String, PyObject, String)} instead,
* it allows creation of substituting code completions * it allows creation of substituting code completions
*/ */
@ -196,15 +196,15 @@ public class PythonCodeCompletionFactory {
} }
/** /**
* Creates a new CodeCompletion from the given Python objects. * Creates a new CodeCompletion from the given Jython objects.
* *
* @param description description of the new CodeCompletion * @param description description of the new CodeCompletion
* @param insertion what will be inserted to make the code complete * @param insertion what will be inserted to make the code complete
* @param pyObj a Python Object * @param pyObj a Jython Object
* @param userInput a word we want to complete, can be an empty string. * @param userInput a word we want to complete, can be an empty string.
* It's used to determine which part (if any) of the input should be * It's used to determine which part (if any) of the input should be
* removed before the insertion of the completion * removed before the insertion of the completion
* @return A new CodeCompletion from the given Python objects. * @return A new CodeCompletion from the given Jython objects.
*/ */
public static CodeCompletion newCodeCompletion(String description, String insertion, public static CodeCompletion newCodeCompletion(String description, String insertion,
PyObject pyObj, String userInput) { PyObject pyObj, String userInput) {
@ -241,11 +241,11 @@ public class PythonCodeCompletionFactory {
} }
/** /**
* Sets up Python code completion Options. * Sets up Jython code completion Options.
* @param plugin python plugin as options owner * @param plugin jython plugin as options owner
* @param options an Options handle * @param options an Options handle
*/ */
public static void setupOptions(PythonPlugin plugin, Options options) { public static void setupOptions(JythonPlugin plugin, Options options) {
includeTypes = options.getBoolean(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT); includeTypes = options.getBoolean(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT);
options.registerOption(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT, null, options.registerOption(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT, null,
INCLUDE_TYPES_DESCRIPTION); INCLUDE_TYPES_DESCRIPTION);
@ -271,20 +271,20 @@ public class PythonCodeCompletionFactory {
includeTypes = ((Boolean) newValue).booleanValue(); includeTypes = ((Boolean) newValue).booleanValue();
} }
else { else {
Msg.error(PythonCodeCompletionFactory.class, "unknown option '" + name + "'"); Msg.error(JythonCodeCompletionFactory.class, "unknown option '" + name + "'");
} }
} }
/** /**
* Returns the Java __call__ methods declared for a Python object. * Returns the Java __call__ methods declared for a Jython object.
* *
* Some Python "methods" in the new-style Python objects are actually * Some Jython "methods" in the new-style Jython objects are actually
* classes in and of themselves, re-implementing __call__ methods to * classes in and of themselves, re-implementing __call__ methods to
* tell us how to call them. This returns an array of those Methods * tell us how to call them. This returns an array of those Methods
* (for code completion help). * (for code completion help).
* *
* @param obj a PyObject * @param obj a PyObject
* @return the Java __call__ methods declared for the Python object * @return the Java __call__ methods declared for the Jython object
*/ */
public static Object[] getCallMethods(PyObject obj) { public static Object[] getCallMethods(PyObject obj) {
List<Method> callMethodList = new ArrayList<>(); List<Method> callMethodList = new ArrayList<>();

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.io.*; import java.io.*;
@ -44,44 +44,44 @@ import ghidra.util.task.*;
import resources.Icons; import resources.Icons;
/** /**
* This plugin provides the interactive Python interpreter. * This plugin provides the interactive Jython interpreter.
*/ */
//@formatter:off //@formatter:off
@PluginInfo( @PluginInfo(
status = PluginStatus.RELEASED, status = PluginStatus.RELEASED,
packageName = CorePluginPackage.NAME, packageName = CorePluginPackage.NAME,
category = PluginCategoryNames.COMMON, category = PluginCategoryNames.COMMON,
shortDescription = "Python Interpreter", shortDescription = "Jython Interpreter",
description = "Provides an interactive Python Interpreter that is tightly integrated with a loaded Ghidra program.", description = "Provides an interactive Jython Interpreter that is tightly integrated with a loaded Ghidra program.",
servicesRequired = { InterpreterPanelService.class }, servicesRequired = { InterpreterPanelService.class },
isSlowInstallation = true isSlowInstallation = true
) )
//@formatter:on //@formatter:on
public class PythonPlugin extends ProgramPlugin public class JythonPlugin extends ProgramPlugin
implements InterpreterConnection, OptionsChangeListener { implements InterpreterConnection, OptionsChangeListener {
private InterpreterConsole console; private InterpreterConsole console;
private GhidraPythonInterpreter interpreter; private GhidraJythonInterpreter interpreter;
private PythonScript interactiveScript; private JythonScript interactiveScript;
private TaskMonitor interactiveTaskMonitor; private TaskMonitor interactiveTaskMonitor;
private PythonPluginInputThread inputThread; private JythonPluginInputThread inputThread;
// Plugin options // Plugin options
private final static String INCLUDE_BUILTINS_LABEL = "Include \"builtins\" in code completion?"; private final static String INCLUDE_BUILTINS_LABEL = "Include \"builtins\" in code completion?";
private final static String INCLUDE_BUILTINS_DESCRIPTION = private final static String INCLUDE_BUILTINS_DESCRIPTION =
"Whether or not to include Python's built-in functions and properties in the pop-up code completion window."; "Whether or not to include Jython's built-in functions and properties in the pop-up code completion window.";
private final static boolean INCLUDE_BUILTINS_DEFAULT = true; private final static boolean INCLUDE_BUILTINS_DEFAULT = true;
private static final Icon ICON = new GIcon("icon.plugin.python"); private static final Icon ICON = new GIcon("icon.plugin.jython");
private boolean includeBuiltins = INCLUDE_BUILTINS_DEFAULT; private boolean includeBuiltins = INCLUDE_BUILTINS_DEFAULT;
/** /**
* Creates a new PythonPlugin object. * Creates a new {@link JythonPlugin} object.
* *
* @param tool The tool associated with this plugin. * @param tool The tool associated with this plugin.
*/ */
public PythonPlugin(PluginTool tool) { public JythonPlugin(PluginTool tool) {
super(tool); super(tool);
} }
@ -95,11 +95,11 @@ public class PythonPlugin extends ProgramPlugin
} }
/** /**
* Gets the plugin's Python interpreter. * Gets the plugin's Jython interpreter.
* *
* @return The plugin's Python interpreter. May be null. * @return The plugin's Jython interpreter. May be null.
*/ */
GhidraPythonInterpreter getInterpreter() { GhidraJythonInterpreter getInterpreter() {
return interpreter; return interpreter;
} }
@ -108,7 +108,7 @@ public class PythonPlugin extends ProgramPlugin
* *
* @return The plugin's interactive script. * @return The plugin's interactive script.
*/ */
PythonScript getInteractiveScript() { JythonScript getInteractiveScript() {
return interactiveScript; return interactiveScript;
} }
@ -172,7 +172,7 @@ public class PythonPlugin extends ProgramPlugin
/** /**
* Resets the interpreter to a new starting state. This is used when the plugin is first * Resets the interpreter to a new starting state. This is used when the plugin is first
* initialized, as well as when an existing interpreter receives a Python exit command. * initialized, as well as when an existing interpreter receives a Jython exit command.
* We used to try to reset the same interpreter, but it was really hard to do that correctly * We used to try to reset the same interpreter, but it was really hard to do that correctly
* so we now just create a brand new one. * so we now just create a brand new one.
* <p> * <p>
@ -181,7 +181,7 @@ public class PythonPlugin extends ProgramPlugin
*/ */
private void resetInterpreter() { private void resetInterpreter() {
TaskLauncher.launchModal("Resetting Python...", () -> { TaskLauncher.launchModal("Resetting Jython...", () -> {
resetInterpreterInBackground(); resetInterpreterInBackground();
}); });
} }
@ -193,23 +193,23 @@ public class PythonPlugin extends ProgramPlugin
if (interpreter == null) { if (interpreter == null) {
// Setup options // Setup options
ToolOptions options = tool.getOptions("Python"); ToolOptions options = tool.getOptions("Jython");
includeBuiltins = options.getBoolean(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT); includeBuiltins = options.getBoolean(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT);
options.registerOption(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT, null, options.registerOption(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT, null,
INCLUDE_BUILTINS_DESCRIPTION); INCLUDE_BUILTINS_DESCRIPTION);
options.addOptionsChangeListener(this); options.addOptionsChangeListener(this);
interpreter = GhidraPythonInterpreter.get(); interpreter = GhidraJythonInterpreter.get();
// Setup code completion. This currently has to be done after the interpreter // Setup code completion. This currently has to be done after the interpreter
// is created. Otherwise an exception will occur. // is created. Otherwise an exception will occur.
PythonCodeCompletionFactory.setupOptions(this, options); JythonCodeCompletionFactory.setupOptions(this, options);
} }
else { else {
inputThread.shutdown(); inputThread.shutdown();
inputThread = null; inputThread = null;
interpreter.cleanup(); interpreter.cleanup();
interpreter = GhidraPythonInterpreter.get(); interpreter = GhidraJythonInterpreter.get();
} }
// Reset the console. // Reset the console.
@ -224,20 +224,20 @@ public class PythonPlugin extends ProgramPlugin
// Print a welcome message. // Print a welcome message.
welcome(); welcome();
// Setup the PythonScript describing the state of the interactive prompt. // Setup the JythonScript describing the state of the interactive prompt.
// This allows things like currentProgram and currentAddress to dynamically reflect // This allows things like currentProgram and currentAddress to dynamically reflect
// what's happening in the listing. Injecting the script hierarchy early here allows // what's happening in the listing. Injecting the script hierarchy early here allows
// code completion to work before commands are entered. // code completion to work before commands are entered.
interactiveScript = new PythonScript(); interactiveScript = new JythonScript();
interactiveScript.set( interactiveScript.set(
new GhidraState(tool, tool.getProject(), getCurrentProgram(), getProgramLocation(), new GhidraState(tool, tool.getProject(), getCurrentProgram(), getProgramLocation(),
getProgramSelection(), getProgramHighlight()), getProgramSelection(), getProgramHighlight()),
interactiveTaskMonitor, new PrintWriter(getConsole().getStdOut())); interactiveTaskMonitor, new PrintWriter(getConsole().getStdOut()));
interpreter.injectScriptHierarchy(interactiveScript); interpreter.injectScriptHierarchy(interactiveScript);
interactiveTaskMonitor = new PythonInteractiveTaskMonitor(console.getStdOut()); interactiveTaskMonitor = new JythonInteractiveTaskMonitor(console.getStdOut());
// Start the input thread that receives python commands to execute. // Start the input thread that receives jython commands to execute.
inputThread = new PythonPluginInputThread(this); inputThread = new JythonPluginInputThread(this);
inputThread.start(); inputThread.start();
} }
@ -252,11 +252,11 @@ public class PythonPlugin extends ProgramPlugin
@Override @Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue, public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) { Object newValue) {
if (optionName.startsWith(PythonCodeCompletionFactory.COMPLETION_LABEL)) { if (optionName.startsWith(JythonCodeCompletionFactory.COMPLETION_LABEL)) {
PythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue); JythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
} }
else if (optionName.equals(PythonCodeCompletionFactory.INCLUDE_TYPES_LABEL)) { else if (optionName.equals(JythonCodeCompletionFactory.INCLUDE_TYPES_LABEL)) {
PythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue); JythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
} }
else if (optionName.equals(INCLUDE_BUILTINS_LABEL)) { else if (optionName.equals(INCLUDE_BUILTINS_LABEL)) {
includeBuiltins = ((Boolean) newValue).booleanValue(); includeBuiltins = ((Boolean) newValue).booleanValue();
@ -284,7 +284,7 @@ public class PythonPlugin extends ProgramPlugin
@Override @Override
public List<CodeCompletion> getCompletions(String cmd, int caretPos) { public List<CodeCompletion> getCompletions(String cmd, int caretPos) {
// Refresh the environment // Refresh the environment
interactiveScript.setSourceFile(new ResourceFile(new File("python"))); interactiveScript.setSourceFile(new ResourceFile(new File("jython")));
interactiveScript.set( interactiveScript.set(
new GhidraState(tool, tool.getProject(), currentProgram, currentLocation, new GhidraState(tool, tool.getProject(), currentProgram, currentLocation,
currentSelection, currentHighlight), currentSelection, currentHighlight),
@ -327,7 +327,7 @@ public class PythonPlugin extends ProgramPlugin
if (interpreter == null) { if (interpreter == null) {
return; return;
} }
interpreter.interrupt(inputThread.getPythonPluginExecutionThread()); interpreter.interrupt(inputThread.getJythonPluginExecutionThread());
console.setPrompt(interpreter.getPrimaryPrompt()); console.setPrompt(interpreter.getPrimaryPrompt());
} }
@ -344,7 +344,7 @@ public class PythonPlugin extends ProgramPlugin
@Override @Override
public String getTitle() { public String getTitle() {
return "Python"; return "Jython";
} }
@Override @Override
@ -361,7 +361,7 @@ public class PythonPlugin extends ProgramPlugin
* Prints a welcome message to the console. * Prints a welcome message to the console.
*/ */
private void welcome() { private void welcome() {
console.getOutWriter().println("Python Interpreter for Ghidra"); console.getOutWriter().println("Jython Interpreter for Ghidra");
console.getOutWriter().println("Based on Jython version " + PySystemState.version); console.getOutWriter().println("Based on Jython version " + PySystemState.version);
console.getOutWriter().println("Press 'F1' for usage instructions"); console.getOutWriter().println("Press 'F1' for usage instructions");
} }
@ -369,20 +369,20 @@ public class PythonPlugin extends ProgramPlugin
/** /**
* Support for cancelling execution using a TaskMonitor. * Support for cancelling execution using a TaskMonitor.
*/ */
class PythonInteractiveTaskMonitor extends TaskMonitorAdapter { class JythonInteractiveTaskMonitor extends TaskMonitorAdapter {
private PrintWriter output = null; private PrintWriter output = null;
public PythonInteractiveTaskMonitor(PrintWriter stdOut) { public JythonInteractiveTaskMonitor(PrintWriter stdOut) {
output = stdOut; output = stdOut;
} }
public PythonInteractiveTaskMonitor(OutputStream stdout) { public JythonInteractiveTaskMonitor(OutputStream stdout) {
this(new PrintWriter(stdout)); this(new PrintWriter(stdout));
} }
@Override @Override
public void setMessage(String message) { public void setMessage(String message) {
output.println("<python-interactive>: " + message); output.println("<jython-interactive>: " + message);
} }
} }
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.File; import java.io.File;
import java.io.PrintWriter; import java.io.PrintWriter;
@ -29,23 +29,24 @@ import ghidra.program.model.listing.Program;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/** /**
* Thread responsible for executing a python command for the plugin. * Thread responsible for executing a jython command for the plugin.
*/ */
class PythonPluginExecutionThread extends Thread { class JythonPluginExecutionThread extends Thread {
private PythonPlugin plugin; private JythonPlugin plugin;
private String cmd; private String cmd;
private AtomicBoolean moreInputWanted; private AtomicBoolean moreInputWanted;
/** /**
* Creates a new python plugin execution thread that executes the given command for the given plugin. * Creates a new jython plugin execution thread that executes the given command for the given
* plugin.
* *
* @param plugin The python plugin to execute the command for. * @param plugin The jython plugin to execute the command for.
* @param cmd The python command to execute. * @param cmd The jython command to execute.
* @param moreInputWanted Gets set to indicate that the executed command expects more input. * @param moreInputWanted Gets set to indicate that the executed command expects more input.
*/ */
PythonPluginExecutionThread(PythonPlugin plugin, String cmd, AtomicBoolean moreInputWanted) { JythonPluginExecutionThread(JythonPlugin plugin, String cmd, AtomicBoolean moreInputWanted) {
super("Python plugin execution thread"); super("Jython plugin execution thread");
this.plugin = plugin; this.plugin = plugin;
this.cmd = cmd; this.cmd = cmd;
@ -56,14 +57,14 @@ class PythonPluginExecutionThread extends Thread {
public void run() { public void run() {
TaskMonitor interactiveTaskMonitor = plugin.getInteractiveTaskMonitor(); TaskMonitor interactiveTaskMonitor = plugin.getInteractiveTaskMonitor();
PythonScript interactiveScript = plugin.getInteractiveScript(); JythonScript interactiveScript = plugin.getInteractiveScript();
Program program = plugin.getCurrentProgram(); Program program = plugin.getCurrentProgram();
// Setup transaction for the execution. // Setup transaction for the execution.
try (Transaction tx = program != null ? program.openTransaction("Python command") : null) { try (Transaction tx = program != null ? program.openTransaction("Jython command") : null) {
// Setup Ghidra state to be passed into interpreter // Setup Ghidra state to be passed into interpreter
interactiveTaskMonitor.clearCancelled(); interactiveTaskMonitor.clearCancelled();
interactiveScript.setSourceFile(new ResourceFile(new File("python"))); interactiveScript.setSourceFile(new ResourceFile(new File("jython")));
PluginTool tool = plugin.getTool(); PluginTool tool = plugin.getTool();
interactiveScript.set( interactiveScript.set(
new GhidraState(tool, tool.getProject(), program, plugin.getProgramLocation(), new GhidraState(tool, tool.getProject(), program, plugin.getProgramLocation(),

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.*; import java.io.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -21,37 +21,37 @@ import java.util.concurrent.atomic.AtomicBoolean;
import ghidra.util.Msg; import ghidra.util.Msg;
/** /**
* Thread responsible for getting interactive lines of python from the plugin. * Thread responsible for getting interactive lines of jython from the plugin.
* This class also kicks off the execution of that line in a new {@link PythonPluginExecutionThread}. * This class also kicks off the execution of that line in a new {@link JythonPluginExecutionThread}.
*/ */
class PythonPluginInputThread extends Thread { class JythonPluginInputThread extends Thread {
private static int generationCount = 0; private static int generationCount = 0;
private final PythonPlugin plugin; private final JythonPlugin plugin;
private final AtomicBoolean moreInputWanted = new AtomicBoolean(false); private final AtomicBoolean moreInputWanted = new AtomicBoolean(false);
private final AtomicBoolean shutdownRequested = new AtomicBoolean(false); private final AtomicBoolean shutdownRequested = new AtomicBoolean(false);
private final InputStream consoleStdin; private final InputStream consoleStdin;
private PythonPluginExecutionThread pythonExecutionThread; private JythonPluginExecutionThread jythonExecutionThread;
/** /**
* Creates a new python input thread that gets a line of python input from the given plugin. * Creates a new jython input thread that gets a line of jython input from the given plugin.
* *
* @param plugin The python plugin to get input from. * @param plugin The jython plugin to get input from.
*/ */
PythonPluginInputThread(PythonPlugin plugin) { JythonPluginInputThread(JythonPlugin plugin) {
super("Python plugin input thread (generation " + ++generationCount + ")"); super("Jython plugin input thread (generation " + ++generationCount + ")");
this.plugin = plugin; this.plugin = plugin;
this.consoleStdin = plugin.getConsole().getStdin(); this.consoleStdin = plugin.getConsole().getStdin();
} }
/** /**
* Gets the last python plugin execution thread that ran. * Gets the last jython plugin execution thread that ran.
* *
* @return The last python plugin execution thread that ran. Could be null if one never ran. * @return The last jython plugin execution thread that ran. Could be null if one never ran.
*/ */
PythonPluginExecutionThread getPythonPluginExecutionThread() { JythonPluginExecutionThread getJythonPluginExecutionThread() {
return pythonExecutionThread; return jythonExecutionThread;
} }
@Override @Override
@ -61,13 +61,13 @@ class PythonPluginInputThread extends Thread {
while (!shutdownRequested.get() && (line = reader.readLine()) != null) { while (!shutdownRequested.get() && (line = reader.readLine()) != null) {
// Execute the line in a new thread // Execute the line in a new thread
pythonExecutionThread = jythonExecutionThread =
new PythonPluginExecutionThread(plugin, line, moreInputWanted); new JythonPluginExecutionThread(plugin, line, moreInputWanted);
pythonExecutionThread.start(); jythonExecutionThread.start();
try { try {
// Wait for the execution to finish // Wait for the execution to finish
pythonExecutionThread.join(); jythonExecutionThread.join();
} }
catch (InterruptedException ie) { catch (InterruptedException ie) {
// Hey we're back... a little earlier than expected, but there must be a reason. // Hey we're back... a little earlier than expected, but there must be a reason.
@ -82,7 +82,7 @@ class PythonPluginInputThread extends Thread {
} }
} }
catch (IOException e) { catch (IOException e) {
Msg.error(PythonPluginInputThread.class, Msg.error(JythonPluginInputThread.class,
"Internal error reading commands from interpreter console. Please reset the interpreter.", "Internal error reading commands from interpreter console. Please reset the interpreter.",
e); e);
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.IOException; import java.io.IOException;
@ -28,7 +28,7 @@ import ghidra.util.exception.CancelledException;
/** /**
* Launcher entry point for running Ghidra from within Jython. * Launcher entry point for running Ghidra from within Jython.
*/ */
public class PythonRun implements GhidraLaunchable { public class JythonRun implements GhidraLaunchable {
@Override @Override
public void launch(GhidraApplicationLayout layout, String[] args) { public void launch(GhidraApplicationLayout layout, String[] args) {
@ -37,25 +37,25 @@ public class PythonRun implements GhidraLaunchable {
ApplicationConfiguration configuration = new HeadlessGhidraApplicationConfiguration(); ApplicationConfiguration configuration = new HeadlessGhidraApplicationConfiguration();
Application.initializeApplication(layout, configuration); Application.initializeApplication(layout, configuration);
// Setup python home directory // Setup jython home directory
try { try {
PythonUtils.setupPythonHomeDir(); JythonUtils.setupJythonHomeDir();
} }
catch (IOException e) { catch (IOException e) {
Msg.showError(PythonRun.class, null, "Python home directory", e.getMessage()); Msg.showError(JythonRun.class, null, "Jython home directory", e.getMessage());
System.exit(1); System.exit(1);
} }
// Setup python cache directory // Setup jython cache directory
try { try {
PythonUtils.setupPythonCacheDir(configuration.getTaskMonitor()); JythonUtils.setupJythonCacheDir(configuration.getTaskMonitor());
} }
catch (IOException e) { catch (IOException e) {
Msg.showError(PythonRun.class, null, "Python cache directory", e.getMessage()); Msg.showError(JythonRun.class, null, "Jython cache directory", e.getMessage());
System.exit(1); System.exit(1);
} }
catch (CancelledException e) { catch (CancelledException e) {
Msg.showError(PythonRun.class, null, "Operation cancelled", e.getMessage()); Msg.showError(JythonRun.class, null, "Operation cancelled", e.getMessage());
System.exit(1); System.exit(1);
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -25,11 +25,11 @@ import ghidra.framework.plugintool.PluginTool;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
/** /**
* A Python version of a {@link GhidraScript}. * A Jython version of a {@link GhidraScript}.
*/ */
public class PythonScript extends GhidraScript { public class JythonScript extends GhidraScript {
static final String PYTHON_INTERPRETER = "ghidra.python.interpreter"; static final String JYTHON_INTERPRETER = "ghidra.jython.interpreter";
private AtomicBoolean interpreterRunning = new AtomicBoolean(); private AtomicBoolean interpreterRunning = new AtomicBoolean();
@ -37,10 +37,10 @@ public class PythonScript extends GhidraScript {
public void run() { public void run() {
// Try to get the interpreter from an existing script state. // Try to get the interpreter from an existing script state.
GhidraPythonInterpreter interpreter = GhidraJythonInterpreter interpreter =
(GhidraPythonInterpreter) state.getEnvironmentVar(PYTHON_INTERPRETER); (GhidraJythonInterpreter) state.getEnvironmentVar(JYTHON_INTERPRETER);
// Are we being called from an already running PythonScript with existing state? // Are we being called from an already running JythonScript with existing state?
if (interpreter != null) { if (interpreter != null) {
runInExistingEnvironment(interpreter); runInExistingEnvironment(interpreter);
} }
@ -51,12 +51,12 @@ public class PythonScript extends GhidraScript {
@Override @Override
public void runScript(String scriptName, GhidraState scriptState) throws Exception { public void runScript(String scriptName, GhidraState scriptState) throws Exception {
GhidraPythonInterpreter interpreter = GhidraJythonInterpreter interpreter =
(GhidraPythonInterpreter) state.getEnvironmentVar(PYTHON_INTERPRETER); (GhidraJythonInterpreter) state.getEnvironmentVar(JYTHON_INTERPRETER);
if (interpreter == null) { if (interpreter == null) {
interpreter = GhidraPythonInterpreter.get(); interpreter = GhidraJythonInterpreter.get();
if (interpreter == null) { if (interpreter == null) {
throw new AssertException("Could not get Ghidra Python interpreter!"); throw new AssertException("Could not get Ghidra Jython interpreter!");
} }
} }
ResourceFile scriptSource = GhidraScriptUtil.findScriptByName(scriptName); ResourceFile scriptSource = GhidraScriptUtil.findScriptByName(scriptName);
@ -71,10 +71,10 @@ public class PythonScript extends GhidraScript {
updateStateFromVariables(); updateStateFromVariables();
} }
if (ghidraScript instanceof PythonScript) { if (ghidraScript instanceof JythonScript) {
ghidraScript.set(scriptState, monitor, writer); ghidraScript.set(scriptState, monitor, writer);
PythonScript pythonScript = (PythonScript) ghidraScript; JythonScript jythonScript = (JythonScript) ghidraScript;
interpreter.execFile(pythonScript.getSourceFile(), pythonScript); interpreter.execFile(jythonScript.getSourceFile(), jythonScript);
} }
else { else {
ghidraScript.execute(scriptState, monitor, writer); ghidraScript.execute(scriptState, monitor, writer);
@ -93,7 +93,7 @@ public class PythonScript extends GhidraScript {
* *
* @param interpreter The existing interpreter to execute from. * @param interpreter The existing interpreter to execute from.
*/ */
private void runInExistingEnvironment(GhidraPythonInterpreter interpreter) { private void runInExistingEnvironment(GhidraJythonInterpreter interpreter) {
interpreter.execFile(sourceFile, this); interpreter.execFile(sourceFile, this);
} }
@ -104,7 +104,7 @@ public class PythonScript extends GhidraScript {
private void runInNewEnvironment() { private void runInNewEnvironment() {
// Create new interpreter and stick it in the script's state. // Create new interpreter and stick it in the script's state.
final GhidraPythonInterpreter interpreter = GhidraPythonInterpreter.get(); final GhidraJythonInterpreter interpreter = GhidraJythonInterpreter.get();
final PrintWriter stdout = getStdOut(); final PrintWriter stdout = getStdOut();
final PrintWriter stderr = getStdErr(); final PrintWriter stderr = getStdErr();
interpreter.setOut(stdout); interpreter.setOut(stdout);
@ -114,11 +114,11 @@ public class PythonScript extends GhidraScript {
// script will use the same interpreter. It is questionable whether or not we should do // script will use the same interpreter. It is questionable whether or not we should do
// this (the new script will get all of the old script's variables), but changing it now // this (the new script will get all of the old script's variables), but changing it now
// could break people's scripts if they expect this behavior. // could break people's scripts if they expect this behavior.
state.addEnvironmentVar(PYTHON_INTERPRETER, interpreter); state.addEnvironmentVar(JYTHON_INTERPRETER, interpreter);
// Execute the script in a new thread. // Execute the script in a new thread.
PythonScriptExecutionThread executionThread = JythonScriptExecutionThread executionThread =
new PythonScriptExecutionThread(this, interpreter, interpreterRunning); new JythonScriptExecutionThread(this, interpreter, interpreterRunning);
interpreterRunning.set(true); interpreterRunning.set(true);
executionThread.start(); executionThread.start();
@ -139,7 +139,7 @@ public class PythonScript extends GhidraScript {
// Cleanup the interpreter, and remove it from the state (once it's cleaned it cannot be // Cleanup the interpreter, and remove it from the state (once it's cleaned it cannot be
// reused) // reused)
interpreter.cleanup(); interpreter.cleanup();
state.removeEnvironmentVar(PYTHON_INTERPRETER); state.removeEnvironmentVar(JYTHON_INTERPRETER);
} }
private PrintWriter getStdOut() { private PrintWriter getStdOut() {
@ -175,6 +175,6 @@ public class PythonScript extends GhidraScript {
@Override @Override
public String getCategory() { public String getCategory() {
return "Python"; return "Jython";
} }
} }

View file

@ -13,31 +13,31 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import org.python.core.PyException; import org.python.core.PyException;
/** /**
* Thread responsible for executing a python script from a file. * Thread responsible for executing a jython script from a file.
*/ */
class PythonScriptExecutionThread extends Thread { class JythonScriptExecutionThread extends Thread {
private PythonScript script; private JythonScript script;
private GhidraPythonInterpreter interpreter; private GhidraJythonInterpreter interpreter;
private AtomicBoolean interpreterRunning; private AtomicBoolean interpreterRunning;
/** /**
* Creates a new python script execution thread that executes the given python script. * Creates a new jython script execution thread that executes the given jython script.
* *
* @param script The python script to execute. * @param script The jython script to execute.
* @param interpreter The python interpreter to use for execution. * @param interpreter The jython interpreter to use for execution.
* @param interpreterRunning Gets set to indicate whether or not the interpreter is still running the script. * @param interpreterRunning Gets set to indicate whether or not the interpreter is still running the script.
*/ */
PythonScriptExecutionThread(PythonScript script, GhidraPythonInterpreter interpreter, JythonScriptExecutionThread(JythonScript script, GhidraJythonInterpreter interpreter,
AtomicBoolean interpreterRunning) { AtomicBoolean interpreterRunning) {
super("Python script execution thread"); super("Jython script execution thread");
this.script = script; this.script = script;
this.interpreter = interpreter; this.interpreter = interpreter;

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.*; import java.io.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -21,7 +21,7 @@ import java.util.regex.Pattern;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.app.script.*; import ghidra.app.script.*;
public class PythonScriptProvider extends GhidraScriptProvider { public class JythonScriptProvider extends GhidraScriptProvider {
private static final Pattern BLOCK_COMMENT = Pattern.compile("'''"); private static final Pattern BLOCK_COMMENT = Pattern.compile("'''");
@ -39,9 +39,9 @@ public class PythonScriptProvider extends GhidraScriptProvider {
* {@inheritDoc} * {@inheritDoc}
* *
* <p> * <p>
* In Python this is a triple single quote sequence, "'''". * In Jython this is a triple single quote sequence, "'''".
* *
* @return the Pattern for Python block comment openings * @return the Pattern for Jython block comment openings
*/ */
@Override @Override
public Pattern getBlockCommentStart() { public Pattern getBlockCommentStart() {
@ -52,9 +52,9 @@ public class PythonScriptProvider extends GhidraScriptProvider {
* {@inheritDoc} * {@inheritDoc}
* *
* <p> * <p>
* In Python this is a triple single quote sequence, "'''". * In Jython this is a triple single quote sequence, "'''".
* *
* @return the Pattern for Python block comment openings * @return the Pattern for Jython block comment openings
*/ */
@Override @Override
public Pattern getBlockCommentEnd() { public Pattern getBlockCommentEnd() {
@ -83,7 +83,7 @@ public class PythonScriptProvider extends GhidraScriptProvider {
@Override @Override
public String getDescription() { public String getDescription() {
return "Python"; return "Jython";
} }
@Override @Override
@ -96,7 +96,7 @@ public class PythonScriptProvider extends GhidraScriptProvider {
throws GhidraScriptLoadException { throws GhidraScriptLoadException {
try { try {
Class<?> clazz = Class.forName(PythonScript.class.getName()); Class<?> clazz = Class.forName(JythonScript.class.getName());
GhidraScript script = (GhidraScript) clazz.getConstructor().newInstance(); GhidraScript script = (GhidraScript) clazz.getConstructor().newInstance();
script.setSourceFile(sourceFile); script.setSourceFile(sourceFile);
return script; return script;

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.*; import java.io.*;
@ -25,83 +25,83 @@ import utilities.util.FileUtilities;
/** /**
* Python utility method class. * Python utility method class.
*/ */
public class PythonUtils { public class JythonUtils {
public static final String PYTHON_NAME = "jython-2.7.3"; public static final String JYTHON_NAME = "jython-2.7.3";
public static final String PYTHON_CACHEDIR = "jython_cachedir"; public static final String JYTHON_CACHEDIR = "jython_cachedir";
public static final String PYTHON_SRC = "python-src"; public static final String JYTHON_SRC = "jython-src";
/** /**
* Sets up the python home directory. This is the directory that has the "Lib" directory in it. * Sets up the jython home directory. This is the directory that has the "Lib" directory in it.
* *
* @return The python home directory. * @return The jython home directory.
* @throws IOException If there was a disk-related problem setting up the home directory. * @throws IOException If there was a disk-related problem setting up the home directory.
*/ */
public static File setupPythonHomeDir() throws IOException { public static File setupJythonHomeDir() throws IOException {
File pythonModuleDir = Application.getMyModuleRootDirectory().getFile(false); File jythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
File pythonHomeDir = File jythonHomeDir =
Application.getModuleDataSubDirectory(pythonModuleDir.getName(), PYTHON_NAME).getFile( Application.getModuleDataSubDirectory(jythonModuleDir.getName(), JYTHON_NAME)
false); .getFile(false);
if (!pythonHomeDir.exists()) { if (!jythonHomeDir.exists()) {
throw new IOException("Failed to find the python home directory at: " + pythonHomeDir); throw new IOException("Failed to find the jython home directory at: " + jythonHomeDir);
} }
System.setProperty("python.home", pythonHomeDir.getAbsolutePath()); System.setProperty("jython.home", jythonHomeDir.getAbsolutePath());
return pythonHomeDir; return jythonHomeDir;
} }
/** /**
* Sets up the python cache directory. This is a temporary space that python source files * Sets up the jython cache directory. This is a temporary space that jython source files
* get compiled to and cached. It should NOT be in the Ghidra installation directory, because * get compiled to and cached. It should NOT be in the Ghidra installation directory, because
* some installations will not have the appropriate directory permissions to create new files in. * some installations will not have the appropriate directory permissions to create new files in.
* *
* @param monitor A monitor to use during the cache directory setup. * @param monitor A monitor to use during the cache directory setup.
* @return The python cache directory. * @return The jython cache directory.
* @throws IOException If there was a disk-related problem setting up the cache directory. * @throws IOException If there was a disk-related problem setting up the cache directory.
* @throws CancelledException If the user cancelled the setup. * @throws CancelledException If the user cancelled the setup.
*/ */
public static File setupPythonCacheDir(TaskMonitor monitor) public static File setupJythonCacheDir(TaskMonitor monitor)
throws CancelledException, IOException { throws CancelledException, IOException {
File devDir = new File(Application.getUserSettingsDirectory(), "dev"); File devDir = new File(Application.getUserSettingsDirectory(), "dev");
File cacheDir = new File(devDir, PYTHON_CACHEDIR); File cacheDir = new File(devDir, JYTHON_CACHEDIR);
if (!FileUtilities.mkdirs(cacheDir)) { if (!FileUtilities.mkdirs(cacheDir)) {
throw new IOException("Failed to create the python cache directory at: " + cacheDir); throw new IOException("Failed to create the jython cache directory at: " + cacheDir);
} }
File pythonSrcDestDir = new File(cacheDir, PYTHON_SRC); File jythonSrcDestDir = new File(cacheDir, JYTHON_SRC);
if (!FileUtilities.createDir(pythonSrcDestDir)) { if (!FileUtilities.createDir(jythonSrcDestDir)) {
throw new IOException( throw new IOException(
"Failed to create the " + PYTHON_SRC + " directory at: " + pythonSrcDestDir); "Failed to create the " + JYTHON_SRC + " directory at: " + jythonSrcDestDir);
} }
File pythonModuleDir = Application.getMyModuleRootDirectory().getFile(false); File jythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
File pythonSrcDir = new File(pythonModuleDir, PYTHON_SRC); File jythonSrcDir = new File(jythonModuleDir, JYTHON_SRC);
if (!pythonSrcDir.exists()) { if (!jythonSrcDir.exists()) {
try { try {
pythonSrcDir = Application.getModuleDataSubDirectory(pythonModuleDir.getName(), jythonSrcDir = Application.getModuleDataSubDirectory(jythonModuleDir.getName(),
PYTHON_SRC).getFile(false); JYTHON_SRC).getFile(false);
} }
catch (FileNotFoundException e) { catch (FileNotFoundException e) {
throw new IOException("Failed to find the module's " + PYTHON_SRC + " directory"); throw new IOException("Failed to find the module's " + JYTHON_SRC + " directory");
} }
} }
try { try {
FileUtilities.copyDir(pythonSrcDir, pythonSrcDestDir, f -> f.getName().endsWith(".py"), FileUtilities.copyDir(jythonSrcDir, jythonSrcDestDir, f -> f.getName().endsWith(".py"),
monitor); monitor);
} }
catch (IOException e) { catch (IOException e) {
throw new IOException( throw new IOException(
"Failed to copy " + PYTHON_SRC + " files to: " + pythonSrcDestDir); "Failed to copy " + JYTHON_SRC + " files to: " + jythonSrcDestDir);
} }
System.setProperty("python.cachedir.skip", "false"); System.setProperty("python.cachedir.skip", "false");
System.setProperty("python.cachedir", cacheDir.getAbsolutePath()); System.setProperty("python.cachedir", cacheDir.getAbsolutePath());
System.setProperty("python.path", pythonSrcDestDir.getAbsolutePath()); System.setProperty("python.path", jythonSrcDestDir.getAbsolutePath());
return cacheDir; return cacheDir;
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import java.io.File; import java.io.File;

View file

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Before After
Before After

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -36,7 +36,7 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
/** /**
* Tests for the Ghidra Python Interpreter's code completion functionality. * Tests for the Ghidra Python Interpreter's code completion functionality.
*/ */
public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTest { public class JythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTest {
private String simpleTestProgram = """ private String simpleTestProgram = """
my_int = 32 my_int = 32
@ -68,13 +68,13 @@ public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTes
@Rule @Rule
public TemporaryFolder tempScriptFolder = new TemporaryFolder(); public TemporaryFolder tempScriptFolder = new TemporaryFolder();
private GhidraPythonInterpreter interpreter; private GhidraJythonInterpreter interpreter;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
GhidraScriptUtil.initialize(new BundleHost(), null); GhidraScriptUtil.initialize(new BundleHost(), null);
interpreter = GhidraPythonInterpreter.get(); interpreter = GhidraJythonInterpreter.get();
executePythonProgram(simpleTestProgram); executeJythonProgram(simpleTestProgram);
} }
@After @After
@ -160,7 +160,7 @@ public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTes
return interpreter.getCommandCompletions(command, false, caretPos); return interpreter.getCommandCompletions(command, false, caretPos);
} }
private void executePythonProgram(String code) { private void executeJythonProgram(String code) {
try { try {
File tempFile = tempScriptFolder.newFile(); File tempFile = tempScriptFolder.newFile();
FileUtils.writeStringToFile(tempFile, code, Charset.defaultCharset()); FileUtils.writeStringToFile(tempFile, code, Charset.defaultCharset());

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -29,16 +29,16 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
/** /**
* Tests the Ghidra python interpreter's functionality. * Tests the Ghidra python interpreter's functionality.
*/ */
public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest { public class JythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
private ByteArrayOutputStream out; private ByteArrayOutputStream out;
private GhidraPythonInterpreter interpreter; private GhidraJythonInterpreter interpreter;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
out = new ByteArrayOutputStream(); out = new ByteArrayOutputStream();
GhidraScriptUtil.initialize(new BundleHost(), null); GhidraScriptUtil.initialize(new BundleHost(), null);
interpreter = GhidraPythonInterpreter.get(); interpreter = GhidraJythonInterpreter.get();
interpreter.setOut(out); interpreter.setOut(out);
interpreter.setErr(out); interpreter.setErr(out);
} }
@ -54,7 +54,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
* Tests that the interpreter's "push" method is working by executing a simple line of python. * Tests that the interpreter's "push" method is working by executing a simple line of python.
*/ */
@Test @Test
public void testPythonPush() { public void testJythonPush() {
final String str = "hi"; final String str = "hi";
interpreter.push("print \"" + str + "\"", null); interpreter.push("print \"" + str + "\"", null);
assertEquals(out.toString().trim(), str); assertEquals(out.toString().trim(), str);
@ -64,7 +64,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
* Tests that the interpreter's "execFile" method is working by executing a simple file of python. * Tests that the interpreter's "execFile" method is working by executing a simple file of python.
*/ */
@Test @Test
public void testPythonExecFile() { public void testJythonExecFile() {
interpreter.execFile(new ResourceFile("ghidra_scripts/python_basics.py"), null); interpreter.execFile(new ResourceFile("ghidra_scripts/python_basics.py"), null);
assertTrue(out.toString().contains("Snoopy")); assertTrue(out.toString().contains("Snoopy"));
} }
@ -74,7 +74,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
* that we install from there. * that we install from there.
*/ */
@Test @Test
public void testPythonSiteCustomize() { public void testJythonSiteCustomize() {
interpreter.push("help", null); interpreter.push("help", null);
assertTrue(out.toString().contains("Press 'F1'")); assertTrue(out.toString().contains("Press 'F1'"));
} }
@ -83,7 +83,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
* Tests that cleaning the interpreter invalidates it. * Tests that cleaning the interpreter invalidates it.
*/ */
@Test @Test
public void testPythonCleanupInvalidation() { public void testJythonCleanupInvalidation() {
interpreter.cleanup(); interpreter.cleanup();
try { try {

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -28,19 +28,19 @@ import ghidra.test.TestEnv;
/** /**
* Tests the Python Plugin functionality. * Tests the Python Plugin functionality.
*/ */
public class PythonPluginTest extends AbstractGhidraHeadedIntegrationTest { public class JythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
private TestEnv env; private TestEnv env;
private PluginTool tool; private PluginTool tool;
private PythonPlugin plugin; private JythonPlugin plugin;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
env = new TestEnv(); env = new TestEnv();
tool = env.getTool(); tool = env.getTool();
GhidraScriptUtil.initialize(new BundleHost(), null); GhidraScriptUtil.initialize(new BundleHost(), null);
tool.addPlugin(PythonPlugin.class.getName()); tool.addPlugin(JythonPlugin.class.getName());
plugin = env.getPlugin(PythonPlugin.class); plugin = env.getPlugin(JythonPlugin.class);
} }
@After @After
@ -53,10 +53,10 @@ public class PythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
* Tests that issuing a reset from the plugin resets the interpreter. * Tests that issuing a reset from the plugin resets the interpreter.
*/ */
@Test @Test
public void testPythonPluginReset() { public void testJythonPluginReset() {
GhidraPythonInterpreter origInterpreter = plugin.getInterpreter(); GhidraJythonInterpreter origInterpreter = plugin.getInterpreter();
plugin.reset(); plugin.reset();
GhidraPythonInterpreter newInterpreter = plugin.getInterpreter(); GhidraJythonInterpreter newInterpreter = plugin.getInterpreter();
assertNotSame(origInterpreter, newInterpreter); assertNotSame(origInterpreter, newInterpreter);
} }
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -31,7 +31,7 @@ import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.ScriptInfo; import ghidra.app.script.ScriptInfo;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest { public class JythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -48,7 +48,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
} }
@Test @Test
public void testDetailedPythonScript() { public void testDetailedJythonScript() {
String descLine1 = "This script exists to check that the info on"; String descLine1 = "This script exists to check that the info on";
String descLine2 = "a script that has extensive documentation is"; String descLine2 = "a script that has extensive documentation is";
String descLine3 = "properly parsed and represented."; String descLine3 = "properly parsed and represented.";
@ -99,7 +99,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
} }
@Test @Test
public void testPythonScriptWithBlockComment() { public void testJythonScriptWithBlockComment() {
String description = "Script with a block comment at the top."; String description = "Script with a block comment at the top.";
String category = "Test"; String category = "Test";
ResourceFile scriptFile = null; ResourceFile scriptFile = null;
@ -129,7 +129,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
} }
@Test @Test
public void testPythonScriptWithBlockCommentAndCertifyHeader() { public void testJythonScriptWithBlockCommentAndCertifyHeader() {
String description = "Script with a block comment at the top."; String description = "Script with a block comment at the top.";
String category = "Test"; String category = "Test";
ResourceFile scriptFile = null; ResourceFile scriptFile = null;
@ -168,7 +168,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
} }
@Test @Test
public void testPythonScriptWithoutBlockComment() { public void testJythonScriptWithoutBlockComment() {
String description = "Script without a block comment at the top."; String description = "Script without a block comment at the top.";
String category = "Test"; String category = "Test";
ResourceFile scriptFile = null; ResourceFile scriptFile = null;
@ -194,7 +194,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
} }
@Test @Test
public void testPythonScriptWithSingleLineBlockComment() { public void testJythonScriptWithSingleLineBlockComment() {
String description = "Script with a block comment at the top."; String description = "Script with a block comment at the top.";
String category = "Test"; String category = "Test";
ResourceFile scriptFile = null; ResourceFile scriptFile = null;

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.python; package ghidra.jython;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -37,7 +37,7 @@ import ghidra.util.task.TaskMonitor;
/** /**
* Tests the Python script functionality. * Tests the Python script functionality.
*/ */
public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest { public class JythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
private TestEnv env; private TestEnv env;
private PluginTool tool; private PluginTool tool;
@ -59,19 +59,19 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
} }
/** /**
* Tests that Python scripts are running correctly. * Tests that Jython scripts are running correctly.
* *
* @throws Exception If an exception occurred while trying to run the script. * @throws Exception If an exception occurred while trying to run the script.
*/ */
@Test @Test
public void testPythonScript() throws Exception { public void testJythonScript() throws Exception {
String script = "ghidra_scripts/python_basics.py"; String script = "ghidra_scripts/python_basics.py";
try { try {
String output = runPythonScript(Application.getModuleFile("Python", script)); String output = runPythonScript(Application.getModuleFile("Jython", script));
assertTrue(output.contains("Snoopy")); assertTrue(output.contains("Snoopy"));
} }
catch (FileNotFoundException e) { catch (FileNotFoundException e) {
fail("Could not find python script: " + script); fail("Could not find jython script: " + script);
} }
catch (Exception e) { catch (Exception e) {
fail("Exception occurred trying to run script: " + e.getMessage()); fail("Exception occurred trying to run script: " + e.getMessage());
@ -79,18 +79,18 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
} }
/** /**
* Tests that Python scripts are running correctly. * Tests that Jython scripts are running correctly.
* *
* @throws Exception If an exception occurred while trying to run the script. * @throws Exception If an exception occurred while trying to run the script.
*/ */
@Test @Test
public void testPythonInterpreterGoneFromState() throws Exception { public void testJythonInterpreterGoneFromState() throws Exception {
String script = "ghidra_scripts/python_basics.py"; String script = "ghidra_scripts/python_basics.py";
try { try {
GhidraState state = GhidraState state =
new GhidraState(env.getTool(), env.getProject(), null, null, null, null); new GhidraState(env.getTool(), env.getProject(), null, null, null, null);
runPythonScript(Application.getModuleFile("Python", script), state); runPythonScript(Application.getModuleFile("Jython", script), state);
assertTrue(state.getEnvironmentVar(PythonScript.PYTHON_INTERPRETER) == null); assertTrue(state.getEnvironmentVar(JythonScript.JYTHON_INTERPRETER) == null);
} }
catch (FileNotFoundException e) { catch (FileNotFoundException e) {
fail("Could not find python script: " + script); fail("Could not find python script: " + script);
@ -125,9 +125,9 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
runSwing(() -> console.clearMessages()); runSwing(() -> console.clearMessages());
PythonScriptProvider scriptProvider = new PythonScriptProvider(); JythonScriptProvider scriptProvider = new JythonScriptProvider();
PrintWriter writer = new PrintWriter(new ByteArrayOutputStream()); PrintWriter writer = new PrintWriter(new ByteArrayOutputStream());
PythonScript script = (PythonScript) scriptProvider.getScriptInstance(scriptFile, writer); JythonScript script = (JythonScript) scriptProvider.getScriptInstance(scriptFile, writer);
script.set(state, TaskMonitor.DUMMY, writer); script.set(state, TaskMonitor.DUMMY, writer);
script.run(); script.run();

View file

@ -1,21 +0,0 @@
[Defaults]
color.fg.plugin.python.syntax.class = color.palette.blue
color.fg.plugin.python.syntax.code = color.palette.darkgreen
color.fg.plugin.python.syntax.function = color.palette.green
color.fg.plugin.python.syntax.instance = color.palette.purple
color.fg.plugin.python.syntax.map = color.palette.steelblue
color.fg.plugin.python.syntax.method = color.palette.teal
color.fg.plugin.python.syntax.null = color.palette.red
color.fg.plugin.python.syntax.number = color.palette.darkgray
color.fg.plugin.python.syntax.package = color.palette.darkred
color.fg.plugin.python.syntax.sequence = color.palette.saddlebrown
color.fg.plugin.python.syntax.special = color.palette.darkgreen
icon.plugin.python = python.png
[Dark Defaults]

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#---------------------------------------- #----------------------------------------
# Ghidra Python launch # Ghidra Jython launch
#---------------------------------------- #----------------------------------------
# Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of # Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of
@ -31,6 +31,6 @@ VMARG_LIST+="-Djava.awt.headless=true "
SCRIPT_FILE="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")" SCRIPT_FILE="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")"
SCRIPT_DIR="${SCRIPT_FILE%/*}" SCRIPT_DIR="${SCRIPT_FILE%/*}"
# Launch Ghidra Python # Launch Ghidra Jython
# DEBUG_ADDRESS set via environment for launch.sh # DEBUG_ADDRESS set via environment for launch.sh
DEBUG_ADDRESS=${DEBUG_ADDRESS} "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" jdk "Ghidra-Python" "${MAXMEM}" "${VMARG_LIST}" ghidra.python.PythonRun "$@" DEBUG_ADDRESS=${DEBUG_ADDRESS} "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" jdk "Ghidra-Jython" "${MAXMEM}" "${VMARG_LIST}" ghidra.jython.JythonRun "$@"

View file

@ -1,4 +1,4 @@
:: Ghidra python launch :: Ghidra jython launch
@echo off @echo off
setlocal setlocal
@ -24,4 +24,4 @@ set DEBUG_ADDRESS=127.0.0.1:13002
set VMARG_LIST=-XX:ParallelGCThreads=2 set VMARG_LIST=-XX:ParallelGCThreads=2
set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2 set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2
call "%~dp0launch.bat" %LAUNCH_MODE% jdk Ghidra-Python "%MAXMEM%" "%VMARG_LIST%" ghidra.python.PythonRun %* call "%~dp0launch.bat" %LAUNCH_MODE% jdk Ghidra-Jython "%MAXMEM%" "%VMARG_LIST%" ghidra.jython.JythonRun %*

View file

@ -36,7 +36,7 @@ import ghidra.app.plugin.core.osgi.BundleStatusComponentProvider;
import ghidra.app.plugin.core.script.*; import ghidra.app.plugin.core.script.*;
import ghidra.app.script.*; import ghidra.app.script.*;
import ghidra.app.services.ConsoleService; import ghidra.app.services.ConsoleService;
import ghidra.python.PythonScriptProvider; import ghidra.jython.JythonScriptProvider;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator { public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator {
@ -223,7 +223,7 @@ public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator
List<GhidraScriptProvider> items = new ArrayList<>(); List<GhidraScriptProvider> items = new ArrayList<>();
JavaScriptProvider javaScriptProvider = new JavaScriptProvider(); JavaScriptProvider javaScriptProvider = new JavaScriptProvider();
items.add(javaScriptProvider); items.add(javaScriptProvider);
items.add(new PythonScriptProvider()); items.add(new JythonScriptProvider());
final PickProviderDialog pickDialog = new PickProviderDialog(items, javaScriptProvider); final PickProviderDialog pickDialog = new PickProviderDialog(items, javaScriptProvider);
runSwing(() -> tool.showDialog(pickDialog), false); runSwing(() -> tool.showDialog(pickDialog), false);