From d461edadcb248507c89418c29af994fffd07ebc6 Mon Sep 17 00:00:00 2001 From: Tom Minka <8955276+tminka@users.noreply.github.com> Date: Mon, 21 Dec 2020 19:50:23 +0000 Subject: [PATCH 1/3] TestPythonEngineProperties.SetPythonPath avoids corrupting the module search path for later tests --- src/embed_tests/TestPythonEngineProperties.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/TestPythonEngineProperties.cs b/src/embed_tests/TestPythonEngineProperties.cs index 6d2d5d6cc..94eab37d8 100644 --- a/src/embed_tests/TestPythonEngineProperties.cs +++ b/src/embed_tests/TestPythonEngineProperties.cs @@ -181,7 +181,22 @@ public void SetProgramName() public void SetPythonPath() { PythonEngine.Initialize(); - string path = PythonEngine.PythonPath; + + dynamic sys = Py.Import("sys"); + var locals = new PyDict(); + locals.SetItem("sys", sys); + var result = PythonEngine.Eval("';'.join(sys.path)", null, locals.Handle); + // This does not work: + //var result = PythonEngine.Eval("import sys\n';'.join(sys.path)"); + string path = (string)result.AsManagedObject(typeof(string)); + + // path should not be set to PythonEngine.PythonPath here. + // PythonEngine.PythonPath gets the default module search path, not the full search path. + // The list sys.path is initialized with this value on interpreter startup; + // it can be (and usually is) modified later to change the search path for loading modules. + // See https://docs.python.org/3/c-api/init.html#c.Py_GetPath + // After PythonPath is set, then PythonEngine.PythonPath will correctly return the full search path. + PythonEngine.Shutdown(); PythonEngine.PythonPath = path; From 5a81268df70a931739fa48f3befb581ee5ad5346 Mon Sep 17 00:00:00 2001 From: Tom Minka <8955276+tminka@users.noreply.github.com> Date: Mon, 21 Dec 2020 22:40:00 +0000 Subject: [PATCH 2/3] SetPythonPath uses System.IO.Path.PathSeparator and imports a module under the new path --- src/embed_tests/TestPythonEngineProperties.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/TestPythonEngineProperties.cs b/src/embed_tests/TestPythonEngineProperties.cs index 94eab37d8..cd8477c82 100644 --- a/src/embed_tests/TestPythonEngineProperties.cs +++ b/src/embed_tests/TestPythonEngineProperties.cs @@ -182,10 +182,22 @@ public void SetPythonPath() { PythonEngine.Initialize(); + const string moduleName = "pytest"; + bool importShouldSucceed; + try + { + Py.Import(moduleName); + importShouldSucceed = true; + } + catch + { + importShouldSucceed = false; + } + dynamic sys = Py.Import("sys"); var locals = new PyDict(); locals.SetItem("sys", sys); - var result = PythonEngine.Eval("';'.join(sys.path)", null, locals.Handle); + var result = PythonEngine.Eval($"'{System.IO.Path.PathSeparator}'.join(sys.path)", null, locals.Handle); // This does not work: //var result = PythonEngine.Eval("import sys\n';'.join(sys.path)"); string path = (string)result.AsManagedObject(typeof(string)); @@ -203,6 +215,8 @@ public void SetPythonPath() PythonEngine.Initialize(); Assert.AreEqual(path, PythonEngine.PythonPath); + if (importShouldSucceed) Py.Import(moduleName); + PythonEngine.Shutdown(); } } From 33e5042e6784d6314e073a9090134208521d6c42 Mon Sep 17 00:00:00 2001 From: Tom Minka <8955276+tminka@users.noreply.github.com> Date: Tue, 22 Dec 2020 17:01:10 +0000 Subject: [PATCH 3/3] SetPythonPath computes the path string in a simpler way --- src/embed_tests/TestPythonEngineProperties.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/embed_tests/TestPythonEngineProperties.cs b/src/embed_tests/TestPythonEngineProperties.cs index cd8477c82..626e3c77f 100644 --- a/src/embed_tests/TestPythonEngineProperties.cs +++ b/src/embed_tests/TestPythonEngineProperties.cs @@ -194,13 +194,8 @@ public void SetPythonPath() importShouldSucceed = false; } - dynamic sys = Py.Import("sys"); - var locals = new PyDict(); - locals.SetItem("sys", sys); - var result = PythonEngine.Eval($"'{System.IO.Path.PathSeparator}'.join(sys.path)", null, locals.Handle); - // This does not work: - //var result = PythonEngine.Eval("import sys\n';'.join(sys.path)"); - string path = (string)result.AsManagedObject(typeof(string)); + string[] paths = Py.Import("sys").GetAttr("path").As(); + string path = string.Join(System.IO.Path.PathSeparator.ToString(), paths); // path should not be set to PythonEngine.PythonPath here. // PythonEngine.PythonPath gets the default module search path, not the full search path.