Repository navigation
Expand file tree
/
Copy pathimp.cs
More file actions
342 lines (278 loc) · 14.7 KB
/
Copy pathimp.cs
File metadata and controls
342 lines (278 loc) · 14.7 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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* [email protected]. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using IronPython.Runtime;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;
[assembly: PythonModule("imp", typeof(IronPython.Modules.PythonImport))]
namespace IronPython.Modules {
public static class PythonImport {
public const string __doc__ = "Provides functions for programmatically creating and importing modules and packages.";
internal const int PythonSource = 1;
internal const int PythonCompiled = 2;
internal const int CExtension = 3;
internal const int PythonResource = 4;
internal const int PackageDirectory = 5;
internal const int CBuiltin = 6;
internal const int PythonFrozen = 7;
internal const int PythonCodeResource = 8;
internal const int SearchError = 0;
internal const int ImporterHook = 9;
private static readonly object _lockCountKey = new object();
[SpecialName]
public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
// set the lock count to zero on the 1st load, don't reset the lock count on reloads
if (!context.HasModuleState(_lockCountKey)) {
context.SetModuleState(_lockCountKey, 0L);
}
}
public static string get_magic() {
return "";
}
public static List get_suffixes() {
return List.FromArrayNoCopy(PythonOps.MakeTuple(".py", "U", PythonSource));
}
public static PythonTuple find_module(CodeContext/*!*/ context, string/*!*/ name) {
if (name == null) throw PythonOps.TypeError("find_module() argument 1 must be string, not None");
return FindBuiltinOrSysPath(context, name);
}
public static PythonTuple find_module(CodeContext/*!*/ context, string/*!*/ name, List path) {
if (name == null) throw PythonOps.TypeError("find_module() argument 1 must be string, not None");
if (path == null) {
return FindBuiltinOrSysPath(context, name);
} else {
return FindModulePath(context, name, path);
}
}
public static object load_module(CodeContext/*!*/ context, string name, PythonFile file, string filename, PythonTuple/*!*/ description) {
if (description == null) {
throw PythonOps.TypeError("load_module() argument 4 must be 3-item sequence, not None");
} else if (description.__len__() != 3) {
throw PythonOps.TypeError("load_module() argument 4 must be sequence of length 3, not {0}", description.__len__());
}
PythonContext pythonContext = PythonContext.GetContext(context);
// already loaded? do reload()
PythonModule module = pythonContext.GetModuleByName(name);
if (module != null) {
Importer.ReloadModule(context, module, file);
return module;
}
int type = PythonContext.GetContext(context).ConvertToInt32(description[2]);
switch (type) {
case PythonSource:
return LoadPythonSource(pythonContext, name, file, filename);
case CBuiltin:
return LoadBuiltinModule(context, name);
case PackageDirectory:
return LoadPackageDirectory(pythonContext, name, filename);
default:
throw PythonOps.TypeError("don't know how to import {0}, (type code {1}", name, type);
}
}
[Documentation("new_module(name) -> module\nCreates a new module without adding it to sys.modules.")]
public static PythonModule/*!*/ new_module(CodeContext/*!*/ context, string/*!*/ name) {
if (name == null) throw PythonOps.TypeError("new_module() argument 1 must be string, not None");
PythonModule res = new PythonModule();
res.__dict__["__name__"] = name;
res.__dict__["__doc__"] = null;
res.__dict__["__package__"] = null;
return res;
}
public static bool lock_held(CodeContext/*!*/ context) {
return GetLockCount(context) != 0;
}
public static void acquire_lock(CodeContext/*!*/ context) {
lock (_lockCountKey) {
SetLockCount(context, GetLockCount(context) + 1);
}
}
public static void release_lock(CodeContext/*!*/ context) {
lock (_lockCountKey) {
long lockCount = GetLockCount(context);
if (lockCount == 0) {
throw PythonOps.RuntimeError("not holding the import lock");
}
SetLockCount(context, lockCount - 1);
}
}
public const int PY_SOURCE = PythonSource;
public const int PY_COMPILED = PythonCompiled;
public const int C_EXTENSION = CExtension;
public const int PY_RESOURCE = PythonResource;
public const int PKG_DIRECTORY = PackageDirectory;
public const int C_BUILTIN = CBuiltin;
public const int PY_FROZEN = PythonFrozen;
public const int PY_CODERESOURCE = PythonCodeResource;
public const int SEARCH_ERROR = SearchError;
public const int IMP_HOOK = ImporterHook;
public static object init_builtin(CodeContext/*!*/ context, string/*!*/ name) {
if (name == null) throw PythonOps.TypeError("init_builtin() argument 1 must be string, not None");
return LoadBuiltinModule(context, name);
}
public static object init_frozen(string name) {
return null;
}
public static object get_frozen_object(string name) {
throw PythonOps.ImportError("No such frozen object named {0}", name);
}
public static int is_builtin(CodeContext/*!*/ context, string/*!*/ name) {
if (name == null) throw PythonOps.TypeError("is_builtin() argument 1 must be string, not None");
Type ty;
if (PythonContext.GetContext(context).BuiltinModules.TryGetValue(name, out ty)) {
if (ty.GetTypeInfo().Assembly == typeof(PythonContext).GetTypeInfo().Assembly) {
// supposedly these can't be re-initialized and return -1 to
// indicate that here, but CPython does allow passing them
// to init_builtin.
return -1;
}
return 1;
}
return 0;
}
public static bool is_frozen(string name) {
return false;
}
public static object load_compiled(string name, string pathname) {
return null;
}
public static object load_compiled(string name, string pathname, PythonFile file) {
return null;
}
public static object load_dynamic(string name, string pathname) {
return null;
}
public static object load_dynamic(string name, string pathname, PythonFile file) {
return null;
}
public static object load_package(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname) {
if (name == null) throw PythonOps.TypeError("load_package() argument 1 must be string, not None");
if (pathname == null) throw PythonOps.TypeError("load_package() argument 2 must be string, not None");
return (Importer.LoadPackageFromSource(context, name, pathname) ??
CreateEmptyPackage(context, name, pathname));
}
private static PythonModule/*!*/ CreateEmptyPackage(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname) {
PythonContext pc = PythonContext.GetContext(context);
PythonModule mod = new PythonModule();
mod.__dict__["__name__"] = name;
mod.__dict__["__path__"] = pathname;
pc.SystemStateModules[name] = mod;
return mod;
}
public static object load_source(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname) {
if (name == null) throw PythonOps.TypeError("load_source() argument 1 must be string, not None");
if (pathname == null) throw PythonOps.TypeError("load_source() argument 2 must be string, not None");
// TODO: is this supposed to open PythonFile with Python-specific behavior?
// we may need to insert additional layer to SourceUnit content provider if so
PythonContext pc = PythonContext.GetContext(context);
if (!pc.DomainManager.Platform.FileExists(pathname)) {
throw PythonOps.IOError("Couldn't find file: {0}", pathname);
}
SourceUnit sourceUnit = pc.CreateFileUnit(pathname, pc.DefaultEncoding, SourceCodeKind.File);
return pc.CompileModule(pathname, name, sourceUnit, ModuleOptions.Initialize);
}
public static object load_source(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname, PythonFile/*!*/ file) {
if (name == null) throw PythonOps.TypeError("load_source() argument 1 must be string, not None");
if (pathname == null) throw PythonOps.TypeError("load_source() argument 2 must be string, not None");
if (pathname == null) throw PythonOps.TypeError("load_source() argument 3 must be file, not None");
return LoadPythonSource(PythonContext.GetContext(context), name, file, pathname);
}
public static object reload(CodeContext/*!*/ context, PythonModule scope) {
return Builtin.reload(context, scope);
}
#region Implementation
private static PythonTuple FindBuiltinOrSysPath(CodeContext/*!*/ context, string/*!*/ name) {
List sysPath;
if (!PythonContext.GetContext(context).TryGetSystemPath(out sysPath)) {
throw PythonOps.ImportError("sys.path must be a list of directory names");
}
return FindModuleBuiltinOrPath(context, name, sysPath);
}
private static PythonTuple FindModulePath(CodeContext/*!*/ context, string name, List path) {
Debug.Assert(path != null);
if (name == null) {
throw PythonOps.TypeError("find_module() argument 1 must be string, not None");
}
PlatformAdaptationLayer pal = context.LanguageContext.DomainManager.Platform;
foreach (object d in path) {
string dir = d as string;
if (dir == null) continue; // skip invalid entries
string pathName = Path.Combine(dir, name);
if (pal.DirectoryExists(pathName)) {
if (pal.FileExists(Path.Combine(pathName, "__init__.py"))) {
return PythonTuple.MakeTuple(null, pathName, PythonTuple.MakeTuple("", "", PackageDirectory));
}
}
string fileName = pathName + ".py";
if (pal.FileExists(fileName)) {
Stream fs = pal.OpenInputFileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
PythonFile pf = PythonFile.Create(context, fs, fileName, "U");
return PythonTuple.MakeTuple(pf, fileName, PythonTuple.MakeTuple(".py", "U", PythonSource));
}
}
throw PythonOps.ImportError("No module named {0}", name);
}
private static PythonTuple FindModuleBuiltinOrPath(CodeContext/*!*/ context, string name, List path) {
if (name.Equals("sys")) return BuiltinModuleTuple(name);
if (name.Equals("clr")) {
context.ShowCls = true;
return BuiltinModuleTuple(name);
}
Type ty;
if (PythonContext.GetContext(context).BuiltinModules.TryGetValue(name, out ty)) {
return BuiltinModuleTuple(name);
}
return FindModulePath(context, name, path);
}
private static PythonTuple BuiltinModuleTuple(string name) {
return PythonTuple.MakeTuple(null, name, PythonTuple.MakeTuple("", "", CBuiltin));
}
private static PythonModule/*!*/ LoadPythonSource(PythonContext/*!*/ context, string/*!*/ name, PythonFile/*!*/ file, string/*!*/ fileName) {
SourceUnit sourceUnit = context.CreateSnippet(file.read(), String.IsNullOrEmpty(fileName) ? null : fileName, SourceCodeKind.File);
return context.CompileModule(fileName, name, sourceUnit, ModuleOptions.Initialize);
}
private static PythonModule/*!*/ LoadPackageDirectory(PythonContext/*!*/ context, string moduleName, string path) {
string initPath = Path.Combine(path, "__init__.py");
SourceUnit sourceUnit = context.CreateFileUnit(initPath, context.DefaultEncoding);
return context.CompileModule(initPath, moduleName, sourceUnit, ModuleOptions.Initialize);
}
private static object LoadBuiltinModule(CodeContext/*!*/ context, string/*!*/ name) {
Assert.NotNull(context, name);
return Importer.ImportBuiltin(context, name);
}
#endregion
private static long GetLockCount(CodeContext/*!*/ context) {
return (long)PythonContext.GetContext(context).GetModuleState(_lockCountKey);
}
private static void SetLockCount(CodeContext/*!*/ context, long lockCount) {
PythonContext.GetContext(context).SetModuleState(_lockCountKey, lockCount);
}
[PythonType]
public sealed class NullImporter {
public NullImporter(string path_string) {
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
public object find_module(params object[] args) {
return null;
}
}
}
}