Skip to content

Commit f8db1b8

Browse files
committed
Keep the clr module dictionary up to date in Python 3.
Track assemblies with types in no namespace as well as those in namespaces.
1 parent 80b19e6 commit f8db1b8

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

src/runtime/assemblymanager.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ internal static void ScanAssembly(Assembly assembly) {
291291
Type[] types = assembly.GetTypes();
292292
for (int i = 0; i < types.Length; i++) {
293293
Type t = types[i];
294-
string ns = t.Namespace;
295-
if ((ns != null) && (!namespaces.ContainsKey(ns))) {
294+
string ns = t.Namespace ?? "";
295+
if (!namespaces.ContainsKey(ns)) {
296296
string[] names = ns.Split('.');
297297
string s = "";
298298
for (int n = 0; n < names.Length; n++) {
@@ -367,7 +367,7 @@ public static List<string> GetNames(string nsname) {
367367
Type[] types = a.GetTypes();
368368
for (int i = 0; i < types.Length; i++) {
369369
Type t = types[i];
370-
if (t.Namespace == nsname) {
370+
if ((t.Namespace ?? "") == nsname) {
371371
names.Add(t.Name);
372372
}
373373
}

src/runtime/importhook.cs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,44 @@ internal static void Shutdown() {
9292
//===================================================================
9393
// Return the clr python module (new reference)
9494
//===================================================================
95-
public static IntPtr GetCLRModule() {
95+
public static IntPtr GetCLRModule(IntPtr? fromList=null) {
9696
root.InitializePreload();
9797
#if (PYTHON32 || PYTHON33 || PYTHON34)
98+
// update the module dictionary with the contents of the root dictionary
99+
root.LoadNames();
100+
IntPtr py_mod_dict = Runtime.PyModule_GetDict(py_clr_module);
101+
IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject**
102+
clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr));
103+
Runtime.PyDict_Update(py_mod_dict, clr_dict);
104+
105+
// find any items from the fromlist and get them from the root if they're not
106+
// aleady in the module dictionary
107+
if (fromList != null && fromList != IntPtr.Zero) {
108+
if (Runtime.PyTuple_Check(fromList.GetValueOrDefault()))
109+
{
110+
Runtime.Incref(py_mod_dict);
111+
PyDict mod_dict = new PyDict(py_mod_dict);
112+
113+
Runtime.Incref(fromList.GetValueOrDefault());
114+
PyTuple from = new PyTuple(fromList.GetValueOrDefault());
115+
foreach (PyObject item in from) {
116+
if (mod_dict.HasKey(item))
117+
continue;
118+
119+
string s = item.AsManagedObject(typeof(string)) as string;
120+
if (null == s)
121+
continue;
122+
123+
ManagedType attr = root.GetAttribute(s, true);
124+
if (null == attr)
125+
continue;
126+
127+
Runtime.Incref(attr.pyHandle);
128+
mod_dict.SetItem(s, new PyObject(attr.pyHandle));
129+
}
130+
}
131+
}
132+
98133
Runtime.Incref(py_clr_module);
99134
return py_clr_module;
100135
#else
@@ -145,12 +180,12 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) {
145180
// do the Incref()ed return here, since we've already found
146181
// the module.
147182
if (mod_name == "clr") {
148-
return GetCLRModule();
183+
return GetCLRModule(fromList);
149184
}
150185
if (mod_name == "CLR") {
151186
Exceptions.deprecation("The CLR module is deprecated. " +
152187
"Please use 'clr'.");
153-
return GetCLRModule();
188+
return GetCLRModule(fromList);
154189
}
155190
string realname = mod_name;
156191
if (mod_name.StartsWith("CLR.")) {

0 commit comments

Comments
 (0)