Skip to content

Commit 9555248

Browse files
authored
Add ability to create module from .NET
New module can be created using new `PyModule(string name, string filename)` constructor. Also: `Runtime.Builtins` returns dictionary, containing system builtins (e.g. `builtins` module) `PyModule.SysModules` returns dictionary, that represents all modules loaded by the system (e.g. `sys.modules`)
1 parent 191bc89 commit 9555248

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

src/embed_tests/TestPyModule.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
using System;
3+
4+
using NUnit.Framework;
5+
6+
using Python.Runtime;
7+
8+
namespace Python.EmbeddingTest
9+
{
10+
public class TestPyModule
11+
{
12+
[OneTimeSetUp]
13+
public void SetUp()
14+
{
15+
PythonEngine.Initialize();
16+
}
17+
18+
[OneTimeTearDown]
19+
public void Dispose()
20+
{
21+
PythonEngine.Shutdown();
22+
}
23+
24+
[Test]
25+
public void TestCreate()
26+
{
27+
using PyScope scope = Py.CreateScope();
28+
29+
Assert.IsFalse(PyModule.SysModules.HasKey("testmod"));
30+
31+
PyModule testmod = new PyModule("testmod");
32+
33+
testmod.SetAttr("testattr1", "True".ToPython());
34+
35+
PyModule.SysModules.SetItem("testmod", testmod);
36+
37+
using PyObject code = PythonEngine.Compile(
38+
"import testmod\n" +
39+
"x = testmod.testattr1"
40+
);
41+
scope.Execute(code);
42+
43+
Assert.IsTrue(scope.TryGet("x", out dynamic x));
44+
Assert.AreEqual("True", x.ToString());
45+
}
46+
}
47+
}

src/runtime/pymodule.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
using System;
2+
using System.Text;
3+
4+
using Python.Runtime.Native;
25

36
namespace Python.Runtime
47
{
58
public class PyModule : PyScope
69
{
710
internal PyModule(ref NewReference reference) : base(ref reference, PyScopeManager.Global) { }
811
public PyModule(PyObject o) : base(o.Reference, PyScopeManager.Global) { }
12+
public PyModule(string name, string filename = null) : this(Create(name, filename)) { }
913

1014
/// <summary>
1115
/// Given a module or package name, import the
@@ -37,5 +41,49 @@ public static PyModule FromString(string name, string code)
3741
PythonException.ThrowIfIsNull(m);
3842
return new PyModule(ref m);
3943
}
44+
45+
private static PyModule Create(string name, string filename=null)
46+
{
47+
if(string.IsNullOrWhiteSpace(name))
48+
{
49+
throw new ArgumentNullException(nameof(name));
50+
}
51+
52+
NewReference op = Runtime.PyModule_New(name);
53+
PythonException.ThrowIfIsNull(op);
54+
55+
if (filename != null)
56+
{
57+
BorrowedReference globals = Runtime.PyModule_GetDict(op);
58+
PythonException.ThrowIfIsNull(globals);
59+
int rc = Runtime.PyDict_SetItemString(globals, "__file__", filename.ToPython().Reference);
60+
PythonException.ThrowIfIsNotZero(rc);
61+
}
62+
63+
return new PyModule(ref op);
64+
}
65+
66+
public void SetBuiltins(PyDict builtins)
67+
{
68+
if(builtins == null || builtins.IsNone())
69+
{
70+
throw new ArgumentNullException(nameof(builtins));
71+
}
72+
73+
BorrowedReference globals = Runtime.PyModule_GetDict(this.Reference);
74+
PythonException.ThrowIfIsNull(globals);
75+
int rc = Runtime.PyDict_SetItemString(globals, "__builtins__", builtins.Reference);
76+
PythonException.ThrowIfIsNotZero(rc);
77+
}
78+
79+
public static PyDict SysModules
80+
{
81+
get
82+
{
83+
BorrowedReference sysModulesRef = Runtime.PyImport_GetModuleDict();
84+
PythonException.ThrowIfIsNull(sysModulesRef);
85+
return new PyDict(sysModulesRef);
86+
}
87+
}
4088
}
4189
}

src/runtime/runtime.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,6 +2280,16 @@ internal static IntPtr GetBuiltins()
22802280
return PyImport_Import(PyIdentifier.builtins);
22812281
}
22822282

2283+
public static PyDict Builtins
2284+
{
2285+
get
2286+
{
2287+
BorrowedReference builtins = PyEval_GetBuiltins();
2288+
PythonException.ThrowIfIsNull(builtins);
2289+
return new PyDict(builtins);
2290+
}
2291+
}
2292+
22832293
internal static class Delegates
22842294
{
22852295
static readonly ILibraryLoader libraryLoader = LibraryLoader.Instance;

0 commit comments

Comments
 (0)