From ca79ae9913d1aa7b3e9049a1972c4033e1ae983f Mon Sep 17 00:00:00 2001 From: bmello4688 Date: Thu, 8 Dec 2022 08:55:30 -0500 Subject: [PATCH 1/6] Allo the setting of the python module file in order to create a virtual package structure --- src/runtime/PythonTypes/PyModule.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/runtime/PythonTypes/PyModule.cs b/src/runtime/PythonTypes/PyModule.cs index 4549678ed..df23c2c80 100644 --- a/src/runtime/PythonTypes/PyModule.cs +++ b/src/runtime/PythonTypes/PyModule.cs @@ -80,9 +80,15 @@ public PyModule Reload() return new PyModule(op.StealOrThrow()); } - public static PyModule FromString(string name, string code) + public static PyModule FromString(string name, string code, string file = "") { - using NewReference c = Runtime.Py_CompileString(code, "none", (int)RunFlagType.File); + //force valid value + if(string.IsNullOrWhiteSpace(file)) + { + file = "none"; + } + + using NewReference c = Runtime.Py_CompileString(code, file, (int)RunFlagType.File); NewReference m = Runtime.PyImport_ExecCodeModule(name, c.BorrowOrThrow()); return new PyModule(m.StealOrThrow()); } From c03d024a9623a8ed0e1978ed88c74d8fa840a6b9 Mon Sep 17 00:00:00 2001 From: bmello4688 Date: Thu, 8 Dec 2022 09:48:40 -0500 Subject: [PATCH 2/6] add test --- src/embed_tests/Modules.cs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/embed_tests/Modules.cs b/src/embed_tests/Modules.cs index a88ab8552..3a2228b0e 100644 --- a/src/embed_tests/Modules.cs +++ b/src/embed_tests/Modules.cs @@ -169,6 +169,41 @@ public void TestScopeClass() } } + /// + /// Create a class in the scope, the class can read variables in the scope. + /// Its methods can write the variables with the help of 'global' keyword. + /// + [Test] + public void TestCreateVirtualPackageStructure() + { + using (Py.GIL()) + { + PyModule.FromString("scope", + "class Class1():\n" + + " def __init__(self, value):\n" + + " self.value = value\n" + + " def call(self, arg):\n" + + " return self.value + bb + arg\n" + //use scope variables + " def update(self, arg):\n" + + " global bb\n" + + " bb = self.value + arg\n" //update scope variable + , "test" + ); + + + dynamic _ps = Py.Import("test.scope"); + _ps.bb = 100; + + dynamic obj1 = _ps.Class1(20); + var result = obj1.call(10).As(); + Assert.AreEqual(130, result); + + obj1.update(10); + result = ps.Get("bb"); + Assert.AreEqual(30, result); + } + } + /// /// Import a python module into the session. /// Equivalent to the Python "import" statement. From f66ae8a1b4326c6c3b34c1e898f2a904b961b2c8 Mon Sep 17 00:00:00 2001 From: bmello4688 Date: Thu, 8 Dec 2022 09:58:56 -0500 Subject: [PATCH 3/6] fixed test --- src/embed_tests/Modules.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/Modules.cs b/src/embed_tests/Modules.cs index 3a2228b0e..e642b8bdb 100644 --- a/src/embed_tests/Modules.cs +++ b/src/embed_tests/Modules.cs @@ -178,8 +178,11 @@ public void TestCreateVirtualPackageStructure() { using (Py.GIL()) { - PyModule.FromString("scope", - "class Class1():\n" + + //parent module + PyModule.FromString("test", ""); + //sub-module + PyModule.FromString("test.scope", + "class Class1():\n" + " def __init__(self, value):\n" + " self.value = value\n" + " def call(self, arg):\n" + From 51fed4dc59957d92af72b6b917ebe1796de68863 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 16 Oct 2023 11:47:07 +0200 Subject: [PATCH 4/6] Handle nitpicks and keep 'ABI' stable --- src/embed_tests/Modules.cs | 20 ++++++++++---------- src/runtime/PythonTypes/PyModule.cs | 11 ++++++++--- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/embed_tests/Modules.cs b/src/embed_tests/Modules.cs index e642b8bdb..4bd453f8e 100644 --- a/src/embed_tests/Modules.cs +++ b/src/embed_tests/Modules.cs @@ -51,7 +51,7 @@ public void TestEval() ps.Set("a", 1); var result = ps.Eval("a + 2"); Assert.AreEqual(3, result); - } + } } /// @@ -186,13 +186,13 @@ public void TestCreateVirtualPackageStructure() " def __init__(self, value):\n" + " self.value = value\n" + " def call(self, arg):\n" + - " return self.value + bb + arg\n" + //use scope variables + " return self.value + bb + arg\n" + // use scope variables " def update(self, arg):\n" + " global bb\n" + - " bb = self.value + arg\n" //update scope variable + " bb = self.value + arg\n" // update scope variable , "test" ); - + dynamic _ps = Py.Import("test.scope"); _ps.bb = 100; @@ -232,7 +232,7 @@ public void TestImportModule() } /// - /// Create a scope and import variables from a scope, + /// Create a scope and import variables from a scope, /// exec Python statements in the scope then discard it. /// [Test] @@ -256,7 +256,7 @@ public void TestImportScope() } /// - /// Create a scope and import variables from a scope, + /// Create a scope and import variables from a scope, /// exec Python statements in the scope then discard it. /// [Test] @@ -279,7 +279,7 @@ public void TestImportAllFromScope() } /// - /// Create a scope and import variables from a scope, + /// Create a scope and import variables from a scope, /// call the function imported. /// [Test] @@ -324,7 +324,7 @@ public void TestImportScopeFunction() public void TestVariables() { using (Py.GIL()) - { + { (ps.Variables() as dynamic)["ee"] = new PyInt(200); var a0 = ps.Get("ee"); Assert.AreEqual(200, a0); @@ -364,8 +364,8 @@ public void TestThread() _ps.res = 0; _ps.bb = 100; _ps.th_cnt = 0; - //add function to the scope - //can be call many times, more efficient than ast + //add function to the scope + //can be call many times, more efficient than ast ps.Exec( "import threading\n"+ "lock = threading.Lock()\n"+ diff --git a/src/runtime/PythonTypes/PyModule.cs b/src/runtime/PythonTypes/PyModule.cs index df23c2c80..243f77ecc 100644 --- a/src/runtime/PythonTypes/PyModule.cs +++ b/src/runtime/PythonTypes/PyModule.cs @@ -80,10 +80,15 @@ public PyModule Reload() return new PyModule(op.StealOrThrow()); } - public static PyModule FromString(string name, string code, string file = "") + public static PyModule FromString(string name, string code) { - //force valid value - if(string.IsNullOrWhiteSpace(file)) + return FromString(name, code, ""); + } + + public static PyModule FromString(string name, string code, string file) + { + // Force valid value + if (string.IsNullOrWhiteSpace(file)) { file = "none"; } From ae0b7606b575a8d6f7d0afd2cd1ba734e48c447b Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 16 Oct 2023 12:10:52 +0200 Subject: [PATCH 5/6] Fix test --- src/embed_tests/Modules.cs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/embed_tests/Modules.cs b/src/embed_tests/Modules.cs index 4bd453f8e..a399214c3 100644 --- a/src/embed_tests/Modules.cs +++ b/src/embed_tests/Modules.cs @@ -178,31 +178,29 @@ public void TestCreateVirtualPackageStructure() { using (Py.GIL()) { - //parent module - PyModule.FromString("test", ""); - //sub-module - PyModule.FromString("test.scope", - "class Class1():\n" + + using var _p1 = PyModule.FromString("test", ""); + // Sub-module + using var _p2 = PyModule.FromString("test.scope", + "class Class1():\n" + " def __init__(self, value):\n" + " self.value = value\n" + " def call(self, arg):\n" + " return self.value + bb + arg\n" + // use scope variables " def update(self, arg):\n" + " global bb\n" + - " bb = self.value + arg\n" // update scope variable - , "test" + " bb = self.value + arg\n", // update scope variable + "test" ); + dynamic ps2 = Py.Import("test.scope"); + ps2.bb = 100; - dynamic _ps = Py.Import("test.scope"); - _ps.bb = 100; - - dynamic obj1 = _ps.Class1(20); + dynamic obj1 = ps2.Class1(20); var result = obj1.call(10).As(); Assert.AreEqual(130, result); obj1.update(10); - result = ps.Get("bb"); + result = ps2.Get("bb"); Assert.AreEqual(30, result); } } From b5ca9bf1e71c6e50e2e364ab6fff5c3ae6feeddc Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 16 Oct 2023 12:19:45 +0200 Subject: [PATCH 6/6] Add test for the new parameter --- src/embed_tests/Modules.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/embed_tests/Modules.cs b/src/embed_tests/Modules.cs index a399214c3..6cab4dd07 100644 --- a/src/embed_tests/Modules.cs +++ b/src/embed_tests/Modules.cs @@ -205,6 +205,26 @@ public void TestCreateVirtualPackageStructure() } } + /// + /// Test setting the file attribute via a FromString parameter + /// + [Test] + public void TestCreateModuleWithFilename() + { + using var _gil = Py.GIL(); + + using var mod = PyModule.FromString("mod", ""); + using var modWithoutName = PyModule.FromString("mod_without_name", "", " "); + using var modNullName = PyModule.FromString("mod_null_name", "", null); + + using var modWithName = PyModule.FromString("mod_with_name", "", "some_filename"); + + Assert.AreEqual("none", mod.Get("__file__")); + Assert.AreEqual("none", modWithoutName.Get("__file__")); + Assert.AreEqual("none", modNullName.Get("__file__")); + Assert.AreEqual("some_filename", modWithName.Get("__file__")); + } + /// /// Import a python module into the session. /// Equivalent to the Python "import" statement.