PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Modules/imp.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 341 lines | 256 code | 64 blank | 21 comment | 55 complexity | 512df75a36c75fc7eb6fd13e1556dfc1 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Diagnostics;
  17. using System.IO;
  18. using System.Runtime.CompilerServices;
  19. using Microsoft.Scripting;
  20. using Microsoft.Scripting.Runtime;
  21. using Microsoft.Scripting.Utils;
  22. using IronPython.Runtime;
  23. using IronPython.Runtime.Operations;
  24. using IronPython.Runtime.Types;
  25. [assembly: PythonModule("imp", typeof(IronPython.Modules.PythonImport))]
  26. namespace IronPython.Modules {
  27. public static class PythonImport {
  28. public const string __doc__ = "Provides functions for programmatically creating and importing modules and packages.";
  29. internal const int PythonSource = 1;
  30. internal const int PythonCompiled = 2;
  31. internal const int CExtension = 3;
  32. internal const int PythonResource = 4;
  33. internal const int PackageDirectory = 5;
  34. internal const int CBuiltin = 6;
  35. internal const int PythonFrozen = 7;
  36. internal const int PythonCodeResource = 8;
  37. internal const int SearchError = 0;
  38. internal const int ImporterHook = 9;
  39. private static readonly object _lockCountKey = new object();
  40. [SpecialName]
  41. public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
  42. // set the lock count to zero on the 1st load, don't reset the lock count on reloads
  43. if (!context.HasModuleState(_lockCountKey)) {
  44. context.SetModuleState(_lockCountKey, 0L);
  45. }
  46. }
  47. public static string get_magic() {
  48. return "";
  49. }
  50. public static List get_suffixes() {
  51. return List.FromArrayNoCopy(PythonOps.MakeTuple(".py", "U", PythonSource));
  52. }
  53. public static PythonTuple find_module(CodeContext/*!*/ context, string/*!*/ name) {
  54. if (name == null) throw PythonOps.TypeError("find_module() argument 1 must be string, not None");
  55. return FindBuiltinOrSysPath(context, name);
  56. }
  57. public static PythonTuple find_module(CodeContext/*!*/ context, string/*!*/ name, List path) {
  58. if (name == null) throw PythonOps.TypeError("find_module() argument 1 must be string, not None");
  59. if (path == null) {
  60. return FindBuiltinOrSysPath(context, name);
  61. } else {
  62. return FindModulePath(context, name, path);
  63. }
  64. }
  65. public static object load_module(CodeContext/*!*/ context, string name, PythonFile file, string filename, PythonTuple/*!*/ description) {
  66. if (description == null) {
  67. throw PythonOps.TypeError("load_module() argument 4 must be 3-item sequence, not None");
  68. } else if (description.__len__() != 3) {
  69. throw PythonOps.TypeError("load_module() argument 4 must be sequence of length 3, not {0}", description.__len__());
  70. }
  71. PythonContext pythonContext = PythonContext.GetContext(context);
  72. // already loaded? do reload()
  73. PythonModule module = pythonContext.GetModuleByName(name);
  74. if (module != null) {
  75. Importer.ReloadModule(context, module, file);
  76. return module;
  77. }
  78. int type = PythonContext.GetContext(context).ConvertToInt32(description[2]);
  79. switch (type) {
  80. case PythonSource:
  81. return LoadPythonSource(pythonContext, name, file, filename);
  82. case CBuiltin:
  83. return LoadBuiltinModule(context, name);
  84. case PackageDirectory:
  85. return LoadPackageDirectory(pythonContext, name, filename);
  86. default:
  87. throw PythonOps.TypeError("don't know how to import {0}, (type code {1}", name, type);
  88. }
  89. }
  90. [Documentation("new_module(name) -> module\nCreates a new module without adding it to sys.modules.")]
  91. public static PythonModule/*!*/ new_module(CodeContext/*!*/ context, string/*!*/ name) {
  92. if (name == null) throw PythonOps.TypeError("new_module() argument 1 must be string, not None");
  93. PythonModule res = new PythonModule();
  94. res.__dict__["__name__"] = name;
  95. res.__dict__["__doc__"] = null;
  96. res.__dict__["__package__"] = null;
  97. return res;
  98. }
  99. public static bool lock_held(CodeContext/*!*/ context) {
  100. return GetLockCount(context) != 0;
  101. }
  102. public static void acquire_lock(CodeContext/*!*/ context) {
  103. lock (_lockCountKey) {
  104. SetLockCount(context, GetLockCount(context) + 1);
  105. }
  106. }
  107. public static void release_lock(CodeContext/*!*/ context) {
  108. lock (_lockCountKey) {
  109. long lockCount = GetLockCount(context);
  110. if (lockCount == 0) {
  111. throw PythonOps.RuntimeError("not holding the import lock");
  112. }
  113. SetLockCount(context, lockCount - 1);
  114. }
  115. }
  116. public const int PY_SOURCE = PythonSource;
  117. public const int PY_COMPILED = PythonCompiled;
  118. public const int C_EXTENSION = CExtension;
  119. public const int PY_RESOURCE = PythonResource;
  120. public const int PKG_DIRECTORY = PackageDirectory;
  121. public const int C_BUILTIN = CBuiltin;
  122. public const int PY_FROZEN = PythonFrozen;
  123. public const int PY_CODERESOURCE = PythonCodeResource;
  124. public const int SEARCH_ERROR = SearchError;
  125. public const int IMP_HOOK = ImporterHook;
  126. public static object init_builtin(CodeContext/*!*/ context, string/*!*/ name) {
  127. if (name == null) throw PythonOps.TypeError("init_builtin() argument 1 must be string, not None");
  128. return LoadBuiltinModule(context, name);
  129. }
  130. public static object init_frozen(string name) {
  131. return null;
  132. }
  133. public static object get_frozen_object(string name) {
  134. throw PythonOps.ImportError("No such frozen object named {0}", name);
  135. }
  136. public static int is_builtin(CodeContext/*!*/ context, string/*!*/ name) {
  137. if (name == null) throw PythonOps.TypeError("is_builtin() argument 1 must be string, not None");
  138. Type ty;
  139. if (PythonContext.GetContext(context).BuiltinModules.TryGetValue(name, out ty)) {
  140. if (ty.Assembly == typeof(PythonContext).Assembly) {
  141. // supposedly these can't be re-initialized and return -1 to
  142. // indicate that here, but CPython does allow passing them
  143. // to init_builtin.
  144. return -1;
  145. }
  146. return 1;
  147. }
  148. return 0;
  149. }
  150. public static bool is_frozen(string name) {
  151. return false;
  152. }
  153. public static object load_compiled(string name, string pathname) {
  154. return null;
  155. }
  156. public static object load_compiled(string name, string pathname, PythonFile file) {
  157. return null;
  158. }
  159. public static object load_dynamic(string name, string pathname) {
  160. return null;
  161. }
  162. public static object load_dynamic(string name, string pathname, PythonFile file) {
  163. return null;
  164. }
  165. public static object load_package(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname) {
  166. if (name == null) throw PythonOps.TypeError("load_package() argument 1 must be string, not None");
  167. if (pathname == null) throw PythonOps.TypeError("load_package() argument 2 must be string, not None");
  168. return (Importer.LoadPackageFromSource(context, name, pathname) ??
  169. CreateEmptyPackage(context, name, pathname));
  170. }
  171. private static PythonModule/*!*/ CreateEmptyPackage(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname) {
  172. PythonContext pc = PythonContext.GetContext(context);
  173. PythonModule mod = new PythonModule();
  174. mod.__dict__["__name__"] = name;
  175. mod.__dict__["__path__"] = pathname;
  176. pc.SystemStateModules[name] = mod;
  177. return mod;
  178. }
  179. public static object load_source(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname) {
  180. if (name == null) throw PythonOps.TypeError("load_source() argument 1 must be string, not None");
  181. if (pathname == null) throw PythonOps.TypeError("load_source() argument 2 must be string, not None");
  182. // TODO: is this supposed to open PythonFile with Python-specific behavior?
  183. // we may need to insert additional layer to SourceUnit content provider if so
  184. PythonContext pc = PythonContext.GetContext(context);
  185. if (!pc.DomainManager.Platform.FileExists(pathname)) {
  186. throw PythonOps.IOError("Couldn't find file: {0}", pathname);
  187. }
  188. SourceUnit sourceUnit = pc.CreateFileUnit(pathname, pc.DefaultEncoding, SourceCodeKind.File);
  189. return pc.CompileModule(pathname, name, sourceUnit, ModuleOptions.Initialize);
  190. }
  191. public static object load_source(CodeContext/*!*/ context, string/*!*/ name, string/*!*/ pathname, PythonFile/*!*/ file) {
  192. if (name == null) throw PythonOps.TypeError("load_source() argument 1 must be string, not None");
  193. if (pathname == null) throw PythonOps.TypeError("load_source() argument 2 must be string, not None");
  194. if (pathname == null) throw PythonOps.TypeError("load_source() argument 3 must be file, not None");
  195. return LoadPythonSource(PythonContext.GetContext(context), name, file, pathname);
  196. }
  197. public static object reload(CodeContext/*!*/ context, PythonModule scope) {
  198. return Builtin.reload(context, scope);
  199. }
  200. #region Implementation
  201. private static PythonTuple FindBuiltinOrSysPath(CodeContext/*!*/ context, string/*!*/ name) {
  202. List sysPath;
  203. if (!PythonContext.GetContext(context).TryGetSystemPath(out sysPath)) {
  204. throw PythonOps.ImportError("sys.path must be a list of directory names");
  205. }
  206. return FindModuleBuiltinOrPath(context, name, sysPath);
  207. }
  208. private static PythonTuple FindModulePath(CodeContext/*!*/ context, string name, List path) {
  209. Debug.Assert(path != null);
  210. if (name == null) {
  211. throw PythonOps.TypeError("find_module() argument 1 must be string, not None");
  212. }
  213. PlatformAdaptationLayer pal = context.LanguageContext.DomainManager.Platform;
  214. foreach (object d in path) {
  215. string dir = d as string;
  216. if (dir == null) continue; // skip invalid entries
  217. string pathName = Path.Combine(dir, name);
  218. if (pal.DirectoryExists(pathName)) {
  219. if (pal.FileExists(Path.Combine(pathName, "__init__.py"))) {
  220. return PythonTuple.MakeTuple(null, pathName, PythonTuple.MakeTuple("", "", PackageDirectory));
  221. }
  222. }
  223. string fileName = pathName + ".py";
  224. if (pal.FileExists(fileName)) {
  225. Stream fs = pal.OpenInputFileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  226. PythonFile pf = PythonFile.Create(context, fs, fileName, "U");
  227. return PythonTuple.MakeTuple(pf, fileName, PythonTuple.MakeTuple(".py", "U", PythonSource));
  228. }
  229. }
  230. throw PythonOps.ImportError("No module named {0}", name);
  231. }
  232. private static PythonTuple FindModuleBuiltinOrPath(CodeContext/*!*/ context, string name, List path) {
  233. if (name.Equals("sys")) return BuiltinModuleTuple(name);
  234. if (name.Equals("clr")) {
  235. context.ShowCls = true;
  236. return BuiltinModuleTuple(name);
  237. }
  238. Type ty;
  239. if (PythonContext.GetContext(context).BuiltinModules.TryGetValue(name, out ty)) {
  240. return BuiltinModuleTuple(name);
  241. }
  242. return FindModulePath(context, name, path);
  243. }
  244. private static PythonTuple BuiltinModuleTuple(string name) {
  245. return PythonTuple.MakeTuple(null, name, PythonTuple.MakeTuple("", "", CBuiltin));
  246. }
  247. private static PythonModule/*!*/ LoadPythonSource(PythonContext/*!*/ context, string/*!*/ name, PythonFile/*!*/ file, string/*!*/ fileName) {
  248. SourceUnit sourceUnit = context.CreateSnippet(file.read(), String.IsNullOrEmpty(fileName) ? null : fileName, SourceCodeKind.File);
  249. return context.CompileModule(fileName, name, sourceUnit, ModuleOptions.Initialize);
  250. }
  251. private static PythonModule/*!*/ LoadPackageDirectory(PythonContext/*!*/ context, string moduleName, string path) {
  252. string initPath = Path.Combine(path, "__init__.py");
  253. SourceUnit sourceUnit = context.CreateFileUnit(initPath, context.DefaultEncoding);
  254. return context.CompileModule(initPath, moduleName, sourceUnit, ModuleOptions.Initialize);
  255. }
  256. private static object LoadBuiltinModule(CodeContext/*!*/ context, string/*!*/ name) {
  257. Assert.NotNull(context, name);
  258. return Importer.ImportBuiltin(context, name);
  259. }
  260. #endregion
  261. private static long GetLockCount(CodeContext/*!*/ context) {
  262. return (long)PythonContext.GetContext(context).GetModuleState(_lockCountKey);
  263. }
  264. private static void SetLockCount(CodeContext/*!*/ context, long lockCount) {
  265. PythonContext.GetContext(context).SetModuleState(_lockCountKey, lockCount);
  266. }
  267. [PythonType]
  268. public sealed class NullImporter {
  269. public NullImporter(string path_string) {
  270. }
  271. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  272. public object find_module(params object[] args) {
  273. return null;
  274. }
  275. }
  276. }
  277. }