Skip to content

Commit 33b107c

Browse files
committed
Move clr module to separate file
1 parent 3c4dd16 commit 33b107c

File tree

2 files changed

+198
-191
lines changed

2 files changed

+198
-191
lines changed

src/runtime/Types/ClrModule.cs

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

0 commit comments

Comments
 (0)