-
Notifications
You must be signed in to change notification settings - Fork 774
Expand file tree
/
Copy pathClrModule.cs
More file actions
198 lines (179 loc) · 6.15 KB
/
ClrModule.cs
File metadata and controls
198 lines (179 loc) · 6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
using System;
using System.Linq;
using System.IO;
using System.Reflection;
namespace Python.Runtime
{
/// <summary>
/// The CLR module is the root handler used by the magic import hook
/// to import assemblies. It has a fixed module name "clr" and doesn't
/// provide a namespace.
/// </summary>
[Serializable]
internal class CLRModule : ModuleObject
{
protected static bool interactive_preload = true;
internal static bool preload;
// XXX Test performance of new features //
internal static bool _SuppressDocs = false;
internal static bool _SuppressOverloads = false;
static CLRModule()
{
Reset();
}
private CLRModule() : base("clr")
{
_namespace = string.Empty;
}
internal static NewReference Create(out CLRModule module)
{
module = new CLRModule();
return module.Alloc();
}
public static void Reset()
{
interactive_preload = true;
preload = false;
// XXX Test performance of new features //
_SuppressDocs = false;
_SuppressOverloads = false;
}
/// <summary>
/// The initializing of the preload hook has to happen as late as
/// possible since sys.ps1 is created after the CLR module is
/// created.
/// </summary>
internal void InitializePreload()
{
if (interactive_preload)
{
interactive_preload = false;
if (!Runtime.PySys_GetObject("ps1").IsNull)
{
preload = true;
}
else
{
Exceptions.Clear();
preload = false;
}
}
}
[ModuleFunction]
public static bool getPreload()
{
return preload;
}
[ModuleFunction]
public static void setPreload(bool preloadFlag)
{
preload = preloadFlag;
}
//[ModuleProperty]
public static bool SuppressDocs
{
get { return _SuppressDocs; }
set { _SuppressDocs = value; }
}
//[ModuleProperty]
public static bool SuppressOverloads
{
get { return _SuppressOverloads; }
set { _SuppressOverloads = value; }
}
[ModuleFunction]
[ForbidPythonThreads]
public static Assembly AddReference(string name)
{
AssemblyManager.UpdatePath();
var origNs = AssemblyManager.GetNamespaces();
Assembly? assembly = AssemblyManager.FindLoadedAssembly(name);
if (assembly == null)
{
assembly = AssemblyManager.LoadAssemblyPath(name);
}
if (assembly == null && AssemblyManager.TryParseAssemblyName(name) is { } parsedName)
{
assembly = AssemblyManager.LoadAssembly(parsedName);
}
if (assembly == null)
{
assembly = AssemblyManager.LoadAssemblyFullPath(name);
}
if (assembly == null)
{
throw new FileNotFoundException($"Unable to find assembly '{name}'.");
}
// Classes that are not in a namespace needs an extra nudge to be found.
ImportHook.UpdateCLRModuleDict();
// A bit heavyhanded, but we can't use the AssemblyManager's AssemblyLoadHandler
// method because it may be called from other threads, leading to deadlocks
// if it is called while Python code is executing.
var currNs = AssemblyManager.GetNamespaces().Except(origNs);
foreach(var ns in currNs)
{
ImportHook.AddNamespaceWithGIL(ns);
}
return assembly;
}
/// <summary>
/// Get a Type instance for a class object.
/// clr.GetClrType(IComparable) gives you the Type for IComparable,
/// that you can e.g. perform reflection on. Similar to typeof(IComparable) in C#
/// or clr.GetClrType(IComparable) in IronPython.
///
/// </summary>
/// <param name="type"></param>
/// <returns>The Type object</returns>
[ModuleFunction]
public static Type GetClrType(Type type)
{
return type;
}
[ModuleFunction]
[ForbidPythonThreads]
public static string FindAssembly(string name)
{
AssemblyManager.UpdatePath();
return AssemblyManager.FindAssembly(name);
}
[ModuleFunction]
public static string[] ListAssemblies(bool verbose)
{
AssemblyName[] assnames = AssemblyManager.ListAssemblies();
var names = new string[assnames.Length];
for (var i = 0; i < assnames.Length; i++)
{
if (verbose)
{
names[i] = assnames[i].FullName;
}
else
{
names[i] = assnames[i].Name;
}
}
return names;
}
/// <summary>
/// Note: This should *not* be called directly.
/// The function that get/import a CLR assembly as a python module.
/// This function should only be called by the import machinery as seen
/// in importhook.cs
/// </summary>
/// <param name="spec">A ModuleSpec Python object</param>
/// <returns>A new reference to the imported module, as a PyObject.</returns>
[ModuleFunction]
[ForbidPythonThreads]
public static PyObject _load_clr_module(PyObject spec)
{
using var modname = spec.GetAttr("name");
string name = modname.As<string?>() ?? throw new ArgumentException("name must not be None");
var mod = ImportHook.Import(name);
return mod;
}
[ModuleFunction]
[ForbidPythonThreads]
public static int _add_pending_namespaces() => ImportHook.AddPendingNamespaces();
}
}