Skip to content

Commit

Permalink
Redirect python print to Dynamo console (DynamoDS#11000)
Browse files Browse the repository at this point in the history
* redirect print to DynamoConsol + update unit test

* comment updates

* Update CPythonEvaluator.cs
  • Loading branch information
SHKnudsen authored and mmisol committed Aug 17, 2020
1 parent 65d7f57 commit bc1639f
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 28 deletions.
46 changes: 37 additions & 9 deletions src/Libraries/DSCPython/CPythonEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ public enum EvaluationState { Begin, Success, Failed }
public static class CPythonEvaluator
{
private const string DynamoSkipAttributeName = "__dynamoskipconversion__";
private const string DynamoPrintFuncName = "__dynamoprint__";
private const string NodeName = "__dynamonodename__";
static PyScope globalScope;
internal static readonly string globalScopeName = "global";

Expand Down Expand Up @@ -200,14 +202,16 @@ public static object EvaluatePythonScript(
var pythonNodeSetupCode = "import sys" + Environment.NewLine + "sys.path = sys.path[0:3]";
scope.Exec(pythonNodeSetupCode);

ProcessAdditionalBindings(scope, bindingNames, bindingValues);
scope.Set(NodeName, ProcessAdditionalBindings(bindingNames, bindingValues).ToPython());

int amt = Math.Min(bindingNames.Count, bindingValues.Count);

for (int i = 0; i < amt; i++)
{
scope.Set((string)bindingNames[i], InputMarshaler.Marshal(bindingValues[i]).ToPython());
}

scope.Exec($"sys.stdout.prefix = {NodeName}");

try
{
Expand Down Expand Up @@ -255,6 +259,16 @@ private static PyScope CreateGlobalScope()
import clr
clr.setPreload(True)
");

// Session is null when running unit tests.
if (ExecutionEvents.ActiveSession != null)
{
dynamic logger = ExecutionEvents.ActiveSession.GetParameterValue(ParameterKeys.Logger);
Action<string> logFunction = msg => logger.Log($"{msg}", LogLevel.ConsoleOnly);
scope.Set(DynamoPrintFuncName, logFunction.ToPython());
scope.Exec(RedirectPrint());
}

return scope;
}

Expand All @@ -265,7 +279,7 @@ import clr
/// <param name="scope">Python scope where execution will occur</param>
/// <param name="bindingNames">List of binding names received for evaluation</param>
/// <param name="bindingValues">List of binding values received for evaluation</param>
private static void ProcessAdditionalBindings(PyScope scope, IList bindingNames, IList bindingValues)
private static string ProcessAdditionalBindings(IList bindingNames, IList bindingValues)
{
const string NodeNameInput = "Name";
string nodeName;
Expand All @@ -282,13 +296,27 @@ private static void ProcessAdditionalBindings(PyScope scope, IList bindingNames,
bindingValues.RemoveAt(0);
}

// Session is null when running unit tests.
if (ExecutionEvents.ActiveSession != null)
{
dynamic logger = ExecutionEvents.ActiveSession.GetParameterValue(ParameterKeys.Logger);
Action<string> logFunction = msg => logger.Log($"{nodeName}: {msg}", LogLevel.ConsoleOnly);
scope.Set("DynamoPrint", logFunction.ToPython());
}
return nodeName;
}

private static string RedirectPrint()
{
return String.Format(@"
import sys
class DynamoStdOut:
def __init__(self, log_func):
self.text = ''
self.log_func = log_func
self.prefix = ''
def write(self, text):
if text == '\n':
self.log_func(self.prefix + ': ' + self.text)
self.text = ''
else:
self.text += text
sys.stdout = DynamoStdOut({0})
", DynamoPrintFuncName);
}

/// <summary>
Expand Down
28 changes: 25 additions & 3 deletions src/Libraries/DSIronPython/IronPythonEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public delegate void EvaluationEventHandler(EvaluationState state,
[IsVisibleInDynamoLibrary(false)]
public static class IronPythonEvaluator
{
private const string DynamoPrintFuncName = "__dynamoprint__";
/// <summary> stores a copy of the previously executed code</summary>
private static string prev_code { get; set; }
/// <summary> stores a copy of the previously compiled engine</summary>
Expand Down Expand Up @@ -127,7 +128,7 @@ public static object EvaluateIronPythonScript(
// For backwards compatibility: "sys" was imported by default due to a bug so we keep it that way
scope.ImportModule("sys");

ProcessAdditionalBindings(scope, bindingNames, bindingValues);
ProcessAdditionalBindings(scope, bindingNames, bindingValues, engine);

int amt = Math.Min(bindingNames.Count, bindingValues.Count);

Expand Down Expand Up @@ -163,7 +164,7 @@ public static object EvaluateIronPythonScript(
/// <param name="scope">Python scope where execution will occur</param>
/// <param name="bindingNames">List of binding names received for evaluation</param>
/// <param name="bindingValues">List of binding values received for evaluation</param>
private static void ProcessAdditionalBindings(ScriptScope scope, IList bindingNames, IList bindingValues)
private static void ProcessAdditionalBindings(ScriptScope scope, IList bindingNames, IList bindingValues, ScriptEngine engine)
{
const string NodeNameInput = "Name";
string nodeName;
Expand All @@ -185,10 +186,31 @@ private static void ProcessAdditionalBindings(ScriptScope scope, IList bindingNa
{
dynamic logger = ExecutionEvents.ActiveSession.GetParameterValue(ParameterKeys.Logger);
Action<string> logFunction = msg => logger.Log($"{nodeName}: {msg}", LogLevel.ConsoleOnly);
scope.SetVariable("DynamoPrint", logFunction);
scope.SetVariable(DynamoPrintFuncName, logFunction);
ScriptSource source = engine.CreateScriptSourceFromString(RedirectPrint());
source.Execute(scope);
}
}

private static string RedirectPrint()
{
return String.Format(@"
import sys
class DynamoStdOut:
def __init__(self, log_func):
self.text = ''
self.log_func = log_func
def write(self, text):
if text == '\n':
self.log_func(self.text)
self.text = ''
else:
self.text += text
sys.stdout = DynamoStdOut({0})
", DynamoPrintFuncName);
}

#region Marshalling

/// <summary>
Expand Down
5 changes: 4 additions & 1 deletion test/Libraries/DynamoPythonTests/PythonTestsWithLogging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ public void DynamoPrintLogsToConsole()
var expectedOutput = "Greeting CPython node: Hello from Python3!!!" + Environment.NewLine
+ "Greeting IronPython node: Hello from Python2!!!" + Environment.NewLine
+ "Greeting CPython String node: Hello from Python3!!!" + Environment.NewLine
+ "Greeting IronPython String node: Hello from Python2!!!" + Environment.NewLine;
+ "Greeting IronPython String node: Hello from Python2!!!" + Environment.NewLine
+ "Multiple print parameter node: Hello Dynamo Print !!!" + Environment.NewLine
+ "Print separator parameter node: Hello_Dynamo_Print_!!!" + Environment.NewLine
+ @"`!""£$%^&*()_+-[{]}#~'@;:|\,<.>/? Special character node: Lot's of special characters!!!" + Environment.NewLine;

CurrentDynamoModel.OpenFileFromPath(Path.Combine(TestDirectory, "core", "python", "DynamoPrint.dyn"));
StringAssert.EndsWith(expectedOutput, CurrentDynamoModel.Logger.LogText);
Expand Down
Loading

0 comments on commit bc1639f

Please sign in to comment.