PyObjectWrapper

PythonManager~ PyObjectWrapper

new PyObjectWrapper()

This object is used to call Python functions.
Examples

Create a Python object in the JavaScript environment using module:PythonManager "createPyObject" function. Then, using that newly created Python object, it's possible to call some Python function.
Note: The functions defined in the Python script are scoped in the 'py' namespace.
A very simple example could be:

//JavaScript file
var myPythonObject = PythonManager.createPyObject("C:/pathToScript/pythonScript.py");

var result = myPythonObject.py.add(6,6); //the name of the function, "add", corresponds to a Python function with the same name defined in a Python script.
MessageLog.trace(result); //show "12" in the MessageLog
#Python file
def add(a,b):
  return a+b

Here below is a more complex example, which use two python scripts

//JavaScript file
var myPythonObject = PythonManager.createPyObject("C:/pathToScript/pythonScript.py");

function inspectObject(obj)
{
  MessageLog.trace(obj + " " + Object.prototype.toString.call(obj));
}

inspectObject(myPythonObject.py.returnInt());    // output "5 [object Number]"
inspectObject(myPythonObject.py.returnFloat());  // output "3.14 [object Number]"
inspectObject(myPythonObject.py.returnString()); // output "mystring [object String]"
inspectObject(myPythonObject.py.returnBool());   // output "True [object Boolean]"
inspectObject(myPythonObject.py.returnNone());   // output "undefined [object global]"
inspectObject(myPythonObject.py.returnTuple());  // output "5,2,str [object Array]"

var returnedMap = myPythonObject.py.returnMap();
inspectObject(returnedMap); // output "[object Object] [object Object]"
Object.keys(returnedMap).forEach(function(k) {
  MessageLog.trace(k + ":" + returnedMap[k]); // output "key1:VAL1"
});

var returnedList = myPythonObject.py.returnList();
inspectObject(returnedList); // output "1,2,5,text [object Array]"
for (var i = 0; i < returnedList.length; i++) {
  MessageLog.trace(returnedList[i]); // output 4 lines with "1", "2", "5", and "text" on each line
}

var returnedNested = myPythonObject.py.returnNested();
inspectObject(returnedNested); // output "1,2,3,4 [object Array]"
for (var i = 0; i < returnedNested.length; i++) {
  MessageLog.trace(returnedNested[i]); // output 2 lines with "1,2" on the first and "3,4" on the second line
}

myPythonObject.py.printMessage():

// Load another Python script. If it uses other Python libraries, it could be necessary define addional path
// in PYTHONPATH environment variable or call addSysPath() as below before creating Python object.
// PythonManager.addSysPath("C:\\Python39\\Lib\\site-packages");
var myPythonObject2 = PythonManager.createPyObject("C:/pathToScript/pythonScript2.py");
myPythonObject2.py.writeFile();

// Specify additional path to use NumPy. It could be done by adding path to sys.path as below for MacOS.
PythonManager.addSysPath("/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python");
// Alternatively, it is possible to use PYTHONPATH environment variable to define additional path.
myPythonObject.py.computationWithNumPy();
#Python file
def returnInt():
  return 5

def returnFloat():
  return 3.14

def returnBool():
  return True

def returnString():
  return "mystring"

def returnNone():
  return None

def returnMap():
  return {'key1': 'VAL1'}

def returnList():
  return [1, 2, 5, "text"]

def returnNested():
  return [[1, 2], [3, 4]]

def returnTuple():
  return (5, 2, "str")

def printMessage():
  # Python standard output is conected to Harmony standard output, therefore
  # print result will be seen when runnung Harmony from a terminal/console.
  # See examples below how output a message in Harmony MessageLog.
  print "message in terminal/console"

def computationWithNumPy():
  import numpy as np
  print "NumPy imported."
  np.random.seed(0)
  print np.random.random_sample()
#Python file2
import os

def writeFile():
  home = os.getenv("HOME")
  with open(home + "/python_output.txt", "w") as file:
    file.write("File created by python script")

It's also possible to add variable, object, function and other script interface to the Python object using the addObject function.
Note: when calling a JavaScript function from Python, you need to use the "call" function. This is not the case for other functions.
Example:

//JavaScript file
var myPythonObject = PythonManager.createPyObject("C:/pathToScript/pythonScript.py");

myPythonObject.addObject("myNumber", 123); 
myPythonObject.py.printVar("myNumber");
myPythonObject.setObject("myNumber", 1234); // override 'myNumber' will new value
myPythonObject.py.printVar("myNumber"); // output "1234"

const person = new Object();
person.firstName = 'John';
person.lastName = 'Doe';
person.fullName = function() { 
  //Using "this" keyword in a function will not work if the object is passed to Python
  return person.firstName + " " + person.lastName;
}
myPythonObject.addObject("personObj", person);
myPythonObject.py.printPersonFullName();

myPythonObject.addObject("messageLog", MessageLog);
myPythonObject.addObject("scene", scene);
myPythonObject.py.showCurrentProjectPathOnMessageLog();
#Python file
def printVar(name):
  print myNumber #in this case, print "123" on the console 
  print globals()[name] #in this case, print "123" on the console 
  
def printPersonFullName():
  print personObj.fullName.call() #print "John Doe" on the console

def showCurrentProjectPathOnMessageLog():
  messageLog.trace(scene.currentProjectPath()) #print the current project path in the MessageLog

Here below is an example how use a global count in Python scripts:

//JavaScript file to initialize the global count
var myPythonCountObject = PythonManager.createPyObject("C:/pathToScript/pythonScriptInitCount.py", "myCount"); 
myPythonCountObject.addObject("globalCount", 0);

//JavaScript file to process and update the global count
var myPythonObject = PythonManager.createPyObject("C:/pathToScript/pythonScript.py"); 
myPythonObject.py.process(); 
#Python file 'pythonScriptInitCount.py'
def printCount():
  print globalCount

# pythonScript.py
import myCount
myCount.globalCount = myCount.globalCount + 1
def process():
  print myCount.printCount()

It's also possible to use a Python script to create a GUI that can control Harmony
This example create a very simple GUI that can print message in the Harmony message log.

//JavaScript file
function pythonScripting()
{   
  var myPythonObject = PythonManager.createPyObject("C:/pathToScript/pythonScript.py");

  myPythonObject.addObject("messageLog",MessageLog);
  myPythonObject.addObject("pythonManager",PythonManager);

  myPythonObject.py.createUI();
 }
#Python file 
from PythonQt.QtGui import *
from PythonQt.QtCore import *

def uiMessage():
 messageLog.trace(input.text)
 input.text = ""
 
def createUI():

 global myUI #this needs to be global otherwise as soon as the function is over, the created UI will be destroy
 global input #this needs to be global since we access it from another function
   
 myUI = QWidget()
 myUI.setParent(pythonManager.appWidget()) #without this line, the UI we create will not be closed when harmony is closing.
 myUI.setWindowFlags(Qt.Window) #this line allow the UI to be in it's own window

 box = QVBoxLayout(myUI)
 input = QLineEdit(myUI)
 box.addWidget(input)
 
 push1 =  QPushButton(myUI)
 push1.text = 'Send text to messageLog'
 push1.connect('clicked()', uiMessage)
 box.addWidget(push1)
 
 push2 =  QPushButton(myUI)
 push2.text = 'this button is not connected'
 box.addWidget(push2)
    
 check =  QCheckBox(myUI)
 check.text = 'Does nothing'  
 box.addWidget(check)
 
 myUI.show()

Methods

addObject(name, value) → {boolean}

Add an abject, variable, function or script interface to the Python object.
Skip adding to avoid object reloading if an object with this name already exists.
Parameters:
Name Type Description
name string Name of the object in Python
value Object Value of the object
Returns:
True if a new object has been added or already existed.
Type
boolean

hasObject(name) → {boolean}

Validate if the Python object contains a variable, object, function or script interface with the specified name.
Parameters:
Name Type Description
name string Name of the object in Python
Returns:
True if an object with the specified name exists.
Type
boolean

setObject(name, value) → {boolean}

Set an object, variable, function or script interface in the Python object. Add a new object with the specified name if not yet existed, else override existing one.
Parameters:
Name Type Description
name string Name of the object in Python
value Object Value of the object
Returns:
True if success.
Type
boolean