PageRenderTime 50ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/Python/Product/IronPython/Interpreter/RemoteInterpreter.cs

https://gitlab.com/SplatoonModdingHub/PTVS
C# | 1236 lines | 1003 code | 175 blank | 58 comment | 191 complexity | 77cb65c0bd10e1c7501bd2e14560096b MD5 | raw file
  1. // Python Tools for Visual Studio
  2. // Copyright(c) Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the License); you may not use
  6. // this file except in compliance with the License. You may obtain a copy of the
  7. // License at http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
  10. // OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
  11. // IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  12. // MERCHANTABLITY OR NON-INFRINGEMENT.
  13. //
  14. // See the Apache Version 2.0 License for specific language governing
  15. // permissions and limitations under the License.
  16. using System;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using System.IO;
  20. using System.Linq;
  21. using System.Numerics;
  22. using System.Reflection;
  23. using System.Runtime.Remoting;
  24. using System.Text;
  25. using IronPython.Hosting;
  26. using IronPython.Modules;
  27. using IronPython.Runtime;
  28. using IronPython.Runtime.Operations;
  29. using IronPython.Runtime.Types;
  30. using Microsoft.PythonTools.Interpreter;
  31. using Microsoft.Scripting;
  32. using Microsoft.Scripting.Actions;
  33. using Microsoft.Scripting.Generation;
  34. using Microsoft.Scripting.Hosting;
  35. using Microsoft.Scripting.Hosting.Providers;
  36. using Microsoft.Scripting.Runtime;
  37. using Microsoft.Win32;
  38. namespace Microsoft.IronPythonTools.Interpreter {
  39. /// <summary>
  40. /// Wraps a Python interpreter which is loaded into a remote app domain. Provides lots of helper
  41. /// methods for inspecting various IronPython objects in the domain and returning results w/o causing
  42. /// type loads in the local domain. We use ObjectIdentityHandle's to pass the objects back and forth
  43. /// which allows the local domain to cache based upon object identity w/o transitioning to this domain
  44. /// to do comparisons.
  45. /// </summary>
  46. class RemoteInterpreter {
  47. private readonly ScriptEngine _engine;
  48. private readonly CodeContext _codeContext;
  49. private readonly CodeContext _codeContextCls;
  50. private readonly TopNamespaceTracker _namespaceTracker;
  51. private readonly Dictionary<object, ObjectIdentityHandle> _members = new Dictionary<object, ObjectIdentityHandle>();
  52. private readonly List<object> _reverseMembers = new List<object>();
  53. private readonly HashSet<string> _assembliesLoadedFromDirectories = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
  54. private readonly Dictionary<string, Assembly> _referencedAssemblies = new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
  55. private string[] _analysisDirs;
  56. private const string _codeCtxType = "IronPython.Runtime.CodeContext";
  57. public RemoteInterpreter()
  58. : this(Python.CreateEngine(new Dictionary<string, object> { { "NoAssemblyResolveHook", true } })) {
  59. }
  60. public RemoteInterpreter(ScriptEngine engine) {
  61. AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
  62. _engine = engine;
  63. var pythonContext = HostingHelpers.GetLanguageContext(_engine) as PythonContext;
  64. _codeContextCls = new ModuleContext(new PythonDictionary(), pythonContext).GlobalContext;
  65. _codeContextCls.ModuleContext.ShowCls = true;
  66. _codeContext = new ModuleContext(
  67. new PythonDictionary(),
  68. HostingHelpers.GetLanguageContext(_engine) as PythonContext
  69. ).GlobalContext;
  70. _namespaceTracker = new TopNamespaceTracker(_codeContext.LanguageContext.DomainManager);
  71. AddAssembly(LoadAssemblyInfo(typeof(string).Assembly));
  72. AddAssembly(LoadAssemblyInfo(typeof(Debug).Assembly));
  73. string installDir = GetPythonInstallDir();
  74. if (installDir != null) {
  75. var dllDir = Path.Combine(installDir, "DLLs");
  76. if (Directory.Exists(dllDir)) {
  77. foreach (var assm in Directory.GetFiles(dllDir)) {
  78. try {
  79. var asm = Assembly.LoadFile(Path.Combine(dllDir, assm));
  80. _engine.Runtime.LoadAssembly(asm);
  81. AddAssembly(LoadAssemblyInfo(asm));
  82. } catch {
  83. }
  84. }
  85. }
  86. }
  87. LoadAssemblies();
  88. }
  89. private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
  90. if (new AssemblyName(args.Name).FullName == typeof(RemoteInterpreterProxy).Assembly.FullName) {
  91. return typeof(RemoteInterpreterProxy).Assembly;
  92. }
  93. if (_analysisDirs != null) {
  94. foreach (var dir in _analysisDirs) {
  95. var name = new AssemblyName(args.Name).Name;
  96. var asm = TryLoad(dir, name, "");
  97. if (asm != null) {
  98. AddLoadedAssembly(dir);
  99. return asm;
  100. }
  101. asm = TryLoad(dir, name, ".dll");
  102. if (asm != null) {
  103. AddLoadedAssembly(dir);
  104. return asm;
  105. }
  106. asm = TryLoad(dir, name, ".exe");
  107. if (asm != null) {
  108. AddLoadedAssembly(dir);
  109. return asm;
  110. }
  111. }
  112. }
  113. return null;
  114. }
  115. private void AddLoadedAssembly(string dir) {
  116. lock (_assembliesLoadedFromDirectories) {
  117. _assembliesLoadedFromDirectories.Add(dir);
  118. }
  119. }
  120. private Assembly TryLoad(string dir, string name, string ext) {
  121. string path = Path.Combine(dir, name + ext);
  122. if (File.Exists(path)) {
  123. try {
  124. return Assembly.Load(File.ReadAllBytes(path));
  125. } catch {
  126. }
  127. }
  128. return null;
  129. }
  130. internal string[] GetBuiltinModuleNames() {
  131. var names = _engine.Operations.GetMember<PythonTuple>(_engine.GetSysModule(), "builtin_module_names");
  132. string[] res = new string[names.Count];
  133. for (int i = 0; i < res.Length; i++) {
  134. res[i] = (string)names[i];
  135. }
  136. return res;
  137. }
  138. internal ObjectIdentityHandle ImportBuiltinModule(string modName) {
  139. PythonModule mod = Importer.Import(_codeContextCls, modName, PythonOps.EmptyTuple, 0) as PythonModule;
  140. Debug.Assert(mod != null);
  141. return MakeHandle(mod);
  142. }
  143. /// <summary>
  144. /// VS seems to load extensions via Assembly.LoadFrom. When an assembly is being loaded via Assembly.Load the CLR fusion probes privatePath
  145. /// set in App.config (devenv.exe.config) first and then tries the code base of the assembly that called Assembly.Load if it was itself loaded via LoadFrom.
  146. /// In order to locate IronPython.Modules correctly, the call to Assembly.Load must originate from an assembly in IronPythonTools installation folder.
  147. /// Although Microsoft.Scripting is also in that folder it can be loaded first by IronRuby and that causes the Assembly.Load to search in IronRuby's
  148. /// installation folder. Adding a reference to IronPython.Modules also makes sure that the assembly is loaded from the same location as IronPythonToolsCore.
  149. /// </summary>
  150. private static void LoadAssemblies() {
  151. GC.KeepAlive(typeof(IronPython.Modules.ArrayModule)); // IronPython.Modules
  152. }
  153. internal static string GetPythonInstallDir() {
  154. using (var ipy = Registry.LocalMachine.OpenSubKey("SOFTWARE\\IronPython")) {
  155. if (ipy != null) {
  156. using (var twoSeven = ipy.OpenSubKey("2.7")) {
  157. if (twoSeven != null) {
  158. var installPath = twoSeven.OpenSubKey("InstallPath");
  159. if (installPath != null) {
  160. var res = installPath.GetValue("") as string;
  161. if (res != null) {
  162. return res;
  163. }
  164. }
  165. }
  166. }
  167. }
  168. }
  169. var paths = Environment.GetEnvironmentVariable("PATH");
  170. if (paths != null) {
  171. foreach (string dir in paths.Split(Path.PathSeparator)) {
  172. try {
  173. if (IronPythonExistsIn(dir)) {
  174. return dir;
  175. }
  176. } catch {
  177. // ignore
  178. }
  179. }
  180. }
  181. return null;
  182. }
  183. private static bool IronPythonExistsIn(string/*!*/ dir) {
  184. return File.Exists(Path.Combine(dir, "ipy.exe"));
  185. }
  186. public ScriptEngine Engine {
  187. get {
  188. return _engine;
  189. }
  190. }
  191. private KeyValuePair<Assembly, TopNamespaceTracker> LoadAssemblyInfo(Assembly assm) {
  192. var nsTracker = new TopNamespaceTracker(_codeContext.LanguageContext.DomainManager);
  193. nsTracker.LoadAssembly(assm);
  194. return new KeyValuePair<Assembly, TopNamespaceTracker>(assm, nsTracker);
  195. }
  196. #region CallAndHandle helpers
  197. private static ObjectHandle CallAndHandle(Func<ObjectHandle> action) {
  198. try {
  199. return action();
  200. } catch (FileLoadException) {
  201. } catch (IOException) {
  202. } catch (CannotUnwrapHandleException) {
  203. }
  204. return null;
  205. }
  206. private static ObjectIdentityHandle CallAndHandle(Func<ObjectIdentityHandle> action) {
  207. try {
  208. return action();
  209. } catch (FileLoadException) {
  210. } catch (IOException) {
  211. } catch (CannotUnwrapHandleException) {
  212. }
  213. return new ObjectIdentityHandle();
  214. }
  215. private static string CallAndHandle(Func<string> action) {
  216. try {
  217. return action();
  218. } catch (FileLoadException) {
  219. } catch (IOException) {
  220. } catch (CannotUnwrapHandleException) {
  221. }
  222. return string.Empty;
  223. }
  224. private static string[] CallAndHandle(Func<string[]> action) {
  225. try {
  226. return action();
  227. } catch (FileLoadException) {
  228. } catch (IOException) {
  229. } catch (CannotUnwrapHandleException) {
  230. }
  231. return new string[0];
  232. }
  233. private static T CallAndHandle<T>(Func<T> action, T defaultValue) {
  234. try {
  235. return action();
  236. } catch (FileLoadException) {
  237. } catch (IOException) {
  238. } catch (CannotUnwrapHandleException) {
  239. }
  240. return defaultValue;
  241. }
  242. private static T CallAndHandle<T>(Func<T> action, Func<T> defaultValueCreator) {
  243. try {
  244. return action();
  245. } catch (FileLoadException) {
  246. } catch (IOException) {
  247. } catch (CannotUnwrapHandleException) {
  248. }
  249. return defaultValueCreator();
  250. }
  251. #endregion
  252. internal ObjectHandle LoadAssemblyByName(string name) {
  253. return CallAndHandle(() => {
  254. Assembly res;
  255. if (_referencedAssemblies.TryGetValue(name, out res) ||
  256. (res = ClrModule.LoadAssemblyByName(CodeContext, name)) != null) {
  257. return new ObjectHandle(res);
  258. }
  259. return null;
  260. });
  261. }
  262. internal ObjectHandle LoadAssemblyByPartialName(string name) {
  263. return CallAndHandle(() => {
  264. var res = ClrModule.LoadAssemblyByPartialName(name);
  265. if (res != null) {
  266. return new ObjectHandle(res);
  267. }
  268. return null;
  269. });
  270. }
  271. internal ObjectHandle LoadAssemblyFromFile(string name) {
  272. return CallAndHandle(() => {
  273. var res = ClrModule.LoadAssemblyFromFile(CodeContext, name);
  274. if (res != null) {
  275. return new ObjectHandle(res);
  276. }
  277. return null;
  278. });
  279. }
  280. internal ObjectHandle LoadAssemblyFromFileWithPath(string name) {
  281. return CallAndHandle(() => {
  282. var res = ClrModule.LoadAssemblyFromFileWithPath(CodeContext, name);
  283. if (res != null) {
  284. return new ObjectHandle(res);
  285. }
  286. return null;
  287. });
  288. }
  289. internal ObjectHandle LoadAssemblyFrom(string path) {
  290. return CallAndHandle(() => {
  291. var res = Assembly.LoadFrom(path);
  292. if (res != null) {
  293. return new ObjectHandle(res);
  294. }
  295. return null;
  296. });
  297. }
  298. private void AddAssembly(KeyValuePair<Assembly, TopNamespaceTracker> assembly) {
  299. _namespaceTracker.LoadAssembly(assembly.Key);
  300. }
  301. public bool AddAssembly(ObjectHandle assembly) {
  302. return CallAndHandle(() => {
  303. var asm = (Assembly)assembly.Unwrap();
  304. return AddAssembly(asm);
  305. }, false);
  306. }
  307. private bool AddAssembly(Assembly asm) {
  308. if (asm != null && !_namespaceTracker.PackageAssemblies.Contains(asm)) {
  309. return _namespaceTracker.LoadAssembly(asm);
  310. }
  311. return false;
  312. }
  313. public bool LoadWpf() {
  314. return CallAndHandle(() => {
  315. var res = AddAssembly(typeof(System.Windows.Markup.XamlReader).Assembly); // PresentationFramework
  316. res |= AddAssembly(typeof(System.Windows.Clipboard).Assembly); // PresentationCore
  317. res |= AddAssembly(typeof(System.Windows.DependencyProperty).Assembly); // WindowsBase
  318. res |= AddAssembly(typeof(System.Xaml.XamlReader).Assembly); // System.Xaml
  319. return res;
  320. }, false);
  321. }
  322. public IList<string> GetModuleNames() {
  323. return CallAndHandle(() => {
  324. return _namespaceTracker.Keys.ToArray();
  325. });
  326. }
  327. public ObjectIdentityHandle LookupNamespace(string name) {
  328. if (!String.IsNullOrWhiteSpace(name)) {
  329. var ns = _namespaceTracker.TryGetPackage(name);
  330. if (ns != null) {
  331. return MakeHandle(ns);
  332. }
  333. }
  334. return new ObjectIdentityHandle();
  335. }
  336. internal bool TryGetMember(object obj, string name, out object value) {
  337. return TryGetMember(_codeContext, obj, name, out value);
  338. }
  339. internal bool TryGetMember(object obj, string name, bool showClr, out object value) {
  340. var cctx = showClr ? _codeContextCls : _codeContext;
  341. return TryGetMember(cctx, obj, name, out value);
  342. }
  343. private bool TryGetMember(CodeContext codeContext, object obj, string name, out object value) {
  344. NamespaceTracker nt = obj as NamespaceTracker;
  345. if (nt != null) {
  346. value = NamespaceTrackerOps.GetCustomMember(codeContext, nt, name);
  347. return value != OperationFailed.Value;
  348. }
  349. object result = Builtin.getattr(codeContext, obj, name, this);
  350. if (result == this) {
  351. value = null;
  352. return false;
  353. } else {
  354. value = result;
  355. return true;
  356. }
  357. }
  358. public CodeContext CodeContext {
  359. get {
  360. return _codeContext;
  361. }
  362. }
  363. internal string[] DirHelper(ObjectIdentityHandle handle, bool showClr) {
  364. return CallAndHandle(() => {
  365. var obj = Unwrap(handle);
  366. NamespaceTracker nt = obj as NamespaceTracker;
  367. if (nt != null) {
  368. return nt.GetMemberNames().ToArray();
  369. }
  370. var dir = TryDir(obj, showClr);
  371. int len = dir.__len__();
  372. string[] result = new string[len];
  373. for (int i = 0; i < len; i++) {
  374. // TODO: validate
  375. result[i] = dir[i] as string;
  376. }
  377. return result;
  378. });
  379. }
  380. private static List TryDir(object obj, bool showClr) {
  381. try {
  382. return showClr ? ClrModule.DirClr(obj) : ClrModule.Dir(obj);
  383. } catch {
  384. // http://pytools.codeplex.com/discussions/279363#post697979
  385. // Work around exceptions coming out of IronPython and the CLR,
  386. // one wouldn't normally expect dir() to throw but it can...
  387. return new List();
  388. }
  389. }
  390. private ObjectIdentityHandle MakeHandle(object member) {
  391. if (member == null) {
  392. return new ObjectIdentityHandle();
  393. }
  394. lock (_members) {
  395. ObjectIdentityHandle handle;
  396. if (!_members.TryGetValue(member, out handle)) {
  397. _members[member] = handle = new ObjectIdentityHandle(_members.Count + 1);
  398. _reverseMembers.Add(member);
  399. }
  400. return handle;
  401. }
  402. }
  403. [Serializable]
  404. private class CannotUnwrapHandleException : Exception {
  405. public CannotUnwrapHandleException() { }
  406. public CannotUnwrapHandleException(string message) : base(message) { }
  407. public CannotUnwrapHandleException(string message, Exception inner) : base(message, inner) { }
  408. protected CannotUnwrapHandleException(
  409. System.Runtime.Serialization.SerializationInfo info,
  410. System.Runtime.Serialization.StreamingContext context)
  411. : base(info, context) { }
  412. }
  413. private object Unwrap(ObjectIdentityHandle handle) {
  414. if (handle.IsNull) {
  415. throw new CannotUnwrapHandleException();
  416. }
  417. lock (_members) {
  418. if (handle.Id > _reverseMembers.Count) {
  419. Debug.Fail("Invalid object identity handle");
  420. throw new CannotUnwrapHandleException();
  421. }
  422. var result = _reverseMembers[handle.Id - 1];
  423. if (result == null) {
  424. throw new CannotUnwrapHandleException();
  425. }
  426. return result;
  427. }
  428. }
  429. internal ObjectKind GetObjectKind(ObjectIdentityHandle value) {
  430. if (value.IsNull) {
  431. return ObjectKind.Constant;
  432. }
  433. var obj = Unwrap(value);
  434. if (obj is PythonModule) {
  435. return ObjectKind.Module;
  436. } else if (obj is PythonType) {
  437. return ObjectKind.Type;
  438. } else if (obj is ConstructorFunction) {
  439. return ObjectKind.ConstructorFunction;
  440. } else if (obj is BuiltinFunction) {
  441. return ObjectKind.BuiltinFunction;
  442. } else if (obj is BuiltinMethodDescriptor) {
  443. return ObjectKind.BuiltinMethodDesc;
  444. } else if (obj is ReflectedField) {
  445. return ObjectKind.ReflectedField;
  446. } else if (obj is ReflectedProperty) {
  447. return ObjectKind.ReflectedProperty;
  448. } else if (obj is ReflectedExtensionProperty) {
  449. return ObjectKind.ReflectedExtensionProperty;
  450. } else if (obj is NamespaceTracker) {
  451. return ObjectKind.NamespaceTracker;
  452. } else if (obj is Method) {
  453. return ObjectKind.Method;
  454. } else if (obj is ClassMethodDescriptor) {
  455. return ObjectKind.ClassMethod;
  456. } else if (obj is PythonTypeTypeSlot) {
  457. return ObjectKind.PythonTypeTypeSlot;
  458. } else if (obj is ReflectedEvent) {
  459. return ObjectKind.ReflectedEvent;
  460. } else if (obj is PythonTypeSlot) {
  461. return ObjectKind.PythonTypeSlot;
  462. } else if (obj is TypeGroup) {
  463. return ObjectKind.TypeGroup;
  464. } else if (obj is bool || obj is int || obj is Complex || obj is string || obj is long || obj is double ||
  465. obj.GetType().IsEnum) {
  466. return ObjectKind.Constant;
  467. }
  468. return ObjectKind.Unknown;
  469. }
  470. #region BuiltinMethodDescriptor Helpers
  471. internal ObjectIdentityHandle GetBuiltinMethodDescriptorTemplate(ObjectIdentityHandle handle) {
  472. return CallAndHandle(() => {
  473. var func = PythonOps.GetBuiltinMethodDescriptorTemplate((BuiltinMethodDescriptor)Unwrap(handle));
  474. return MakeHandle(func);
  475. });
  476. }
  477. #endregion
  478. #region PythonModule Helpers
  479. internal string GetModuleDocumentation(ObjectIdentityHandle handle) {
  480. return CallAndHandle(() => {
  481. PythonModule module = (PythonModule)Unwrap(handle);
  482. object docValue;
  483. if (!module.Get__dict__().TryGetValue("__doc__", out docValue) || !(docValue is string)) {
  484. return String.Empty;
  485. }
  486. return (string)docValue;
  487. });
  488. }
  489. internal string GetModuleName(ObjectIdentityHandle handle) {
  490. return CallAndHandle(() => {
  491. PythonModule module = (PythonModule)Unwrap(handle);
  492. object name;
  493. if (!module.Get__dict__().TryGetValue("__name__", out name) || !(name is string)) {
  494. name = "";
  495. }
  496. return (string)name;
  497. });
  498. }
  499. #endregion
  500. #region PythonType Helpers
  501. internal string GetPythonTypeName(ObjectIdentityHandle handle) {
  502. return CallAndHandle(() => {
  503. return PythonType.Get__name__((PythonType)Unwrap(handle));
  504. });
  505. }
  506. internal string GetPythonTypeDocumentation(ObjectIdentityHandle handle) {
  507. return CallAndHandle(() => {
  508. try {
  509. return PythonType.Get__doc__(CodeContext, (PythonType)Unwrap(handle)) as string;
  510. } catch (ArgumentException) {
  511. // IronPython can throw here if it can't figure out the
  512. // path of the assembly this type is defined in.
  513. return null;
  514. }
  515. });
  516. }
  517. internal ObjectIdentityHandle[] GetPythonTypeMro(ObjectIdentityHandle handle) {
  518. return CallAndHandle(() => {
  519. var mro = PythonType.Get__mro__((PythonType)Unwrap(handle));
  520. var mroHandles = new List<ObjectIdentityHandle>();
  521. foreach (var item in mro.OfType<PythonType>()) {
  522. mroHandles.Add(MakeHandle(item));
  523. }
  524. return mroHandles.ToArray();
  525. }, () => new ObjectIdentityHandle[0]);
  526. }
  527. internal BuiltinTypeId PythonTypeGetBuiltinTypeId(ObjectIdentityHandle handle) {
  528. return CallAndHandle(() => {
  529. var value = (PythonType)Unwrap(handle);
  530. var clrType = value.__clrtype__();
  531. switch (Type.GetTypeCode(value.__clrtype__())) {
  532. case TypeCode.Boolean: return BuiltinTypeId.Bool;
  533. case TypeCode.Int32: return BuiltinTypeId.Int;
  534. case TypeCode.String: return BuiltinTypeId.Unicode;
  535. case TypeCode.Double: return BuiltinTypeId.Float;
  536. case TypeCode.Object:
  537. if (clrType == typeof(object)) {
  538. return BuiltinTypeId.Object;
  539. } else if (clrType == typeof(PythonFunction)) {
  540. return BuiltinTypeId.Function;
  541. } else if (clrType == typeof(BuiltinFunction)) {
  542. return BuiltinTypeId.BuiltinFunction;
  543. } else if (clrType == typeof(BuiltinMethodDescriptor)) {
  544. return BuiltinTypeId.BuiltinMethodDescriptor;
  545. } else if (clrType == typeof(Complex)) {
  546. return BuiltinTypeId.Complex;
  547. } else if (clrType == typeof(PythonDictionary)) {
  548. return BuiltinTypeId.Dict;
  549. } else if (clrType == typeof(BigInteger)) {
  550. return BuiltinTypeId.Long;
  551. } else if (clrType == typeof(List)) {
  552. return BuiltinTypeId.List;
  553. } else if (clrType == typeof(PythonGenerator)) {
  554. return BuiltinTypeId.Generator;
  555. } else if (clrType == typeof(SetCollection)) {
  556. return BuiltinTypeId.Set;
  557. } else if (clrType == typeof(PythonType)) {
  558. return BuiltinTypeId.Type;
  559. } else if (clrType == typeof(PythonTuple)) {
  560. return BuiltinTypeId.Tuple;
  561. } else if (clrType == typeof(Bytes)) {
  562. return BuiltinTypeId.Bytes;
  563. }
  564. break;
  565. }
  566. return BuiltinTypeId.Unknown;
  567. }, BuiltinTypeId.Unknown);
  568. }
  569. internal string GetTypeDeclaringModule(ObjectIdentityHandle pythonType) {
  570. return CallAndHandle(() => {
  571. var value = (PythonType)Unwrap(pythonType);
  572. return (string)PythonType.Get__module__(CodeContext, value);
  573. });
  574. }
  575. internal bool IsPythonTypeArray(ObjectIdentityHandle pythonType) {
  576. return CallAndHandle(() => {
  577. var value = (PythonType)Unwrap(pythonType);
  578. return value.__clrtype__().IsArray;
  579. }, false);
  580. }
  581. internal ObjectIdentityHandle GetPythonTypeElementType(ObjectIdentityHandle pythonType) {
  582. return CallAndHandle(() => {
  583. var value = (PythonType)Unwrap(pythonType);
  584. return MakeHandle(DynamicHelpers.GetPythonTypeFromType(value.__clrtype__().GetElementType()));
  585. });
  586. }
  587. internal bool IsDelegateType(ObjectIdentityHandle pythonType) {
  588. return CallAndHandle(() => {
  589. var value = (PythonType)Unwrap(pythonType);
  590. return typeof(Delegate).IsAssignableFrom(value.__clrtype__());
  591. }, false);
  592. }
  593. internal ObjectIdentityHandle[] GetEventInvokeArgs(ObjectIdentityHandle pythonType) {
  594. return CallAndHandle(() => {
  595. var value = (PythonType)Unwrap(pythonType);
  596. var type = value.__clrtype__();
  597. return GetEventInvokeArgs(type);
  598. }, () => new ObjectIdentityHandle[0]);
  599. }
  600. private ObjectIdentityHandle[] GetEventInvokeArgs(Type type) {
  601. return CallAndHandle(() => {
  602. var p = type.GetMethod("Invoke").GetParameters();
  603. var args = new ObjectIdentityHandle[p.Length];
  604. for (int i = 0; i < p.Length; i++) {
  605. args[i] = MakeHandle(DynamicHelpers.GetPythonTypeFromType(p[i].ParameterType));
  606. }
  607. return args;
  608. }, () => new ObjectIdentityHandle[0]);
  609. }
  610. internal PythonMemberType GetPythonTypeMemberType(ObjectIdentityHandle pythonType) {
  611. return CallAndHandle(() => {
  612. var value = (PythonType)Unwrap(pythonType);
  613. var type = value.__clrtype__();
  614. if (type.IsEnum) {
  615. return PythonMemberType.Enum;
  616. } else if (typeof(Delegate).IsAssignableFrom(type)) {
  617. return PythonMemberType.Delegate;
  618. } else {
  619. return PythonMemberType.Class;
  620. }
  621. }, PythonMemberType.Class);
  622. }
  623. internal bool PythonTypeHasNewOrInitMethods(ObjectIdentityHandle pythonType) {
  624. return CallAndHandle(() => {
  625. var value = (PythonType)Unwrap(pythonType);
  626. return PythonTypeHasNewOrInitMethods(value);
  627. }, false);
  628. }
  629. private static bool PythonTypeHasNewOrInitMethods(PythonType value) {
  630. return CallAndHandle(() => {
  631. var clrType = ClrModule.GetClrType(value);
  632. if (!(value == TypeCache.String ||
  633. value == TypeCache.Object ||
  634. value == TypeCache.Double ||
  635. value == TypeCache.Complex ||
  636. value == TypeCache.Boolean)) {
  637. var newMethods = clrType.GetMember("__new__", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static);
  638. if (newMethods.Length == 0) {
  639. var initMethods = clrType.GetMember("__init__", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance);
  640. return initMethods.Length != 0;
  641. }
  642. return true;
  643. } else if (clrType == typeof(object)) {
  644. return false;
  645. }
  646. return true;
  647. }, false);
  648. }
  649. internal ObjectIdentityHandle PythonTypeMakeGenericType(ObjectIdentityHandle pythonType, ObjectIdentityHandle[] types) {
  650. return CallAndHandle(() => {
  651. var value = (PythonType)Unwrap(pythonType);
  652. Type[] realTypes = new Type[types.Length];
  653. for (int i = 0; i < types.Length; i++) {
  654. realTypes[i] = ((PythonType)Unwrap(types[i])).__clrtype__();
  655. }
  656. return MakeHandle(DynamicHelpers.GetPythonTypeFromType(value.__clrtype__().MakeGenericType(realTypes)));
  657. });
  658. }
  659. internal ObjectIdentityHandle[] GetPythonTypeConstructors(ObjectIdentityHandle pythonType) {
  660. return CallAndHandle(() => {
  661. var value = (PythonType)Unwrap(pythonType);
  662. Type clrType = ClrModule.GetClrType(value);
  663. var ctors = clrType.GetConstructors(BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance);
  664. if (ctors.Length > 0) {
  665. ObjectIdentityHandle[] res = new ObjectIdentityHandle[ctors.Length];
  666. for (int i = 0; i < res.Length; i++) {
  667. res[i] = MakeHandle(ctors[i]);
  668. }
  669. return res;
  670. }
  671. return null;
  672. }, () => new ObjectIdentityHandle[0]);
  673. }
  674. internal bool IsPythonTypeGenericTypeDefinition(ObjectIdentityHandle pythonType) {
  675. return CallAndHandle(() => {
  676. var value = (PythonType)Unwrap(pythonType);
  677. return value.__clrtype__().IsGenericTypeDefinition;
  678. }, false);
  679. }
  680. #endregion
  681. #region ReflectedField Helpers
  682. internal string GetFieldDocumentation(ObjectIdentityHandle field) {
  683. return CallAndHandle(() => {
  684. var value = (ReflectedField)Unwrap(field);
  685. try {
  686. return value.__doc__;
  687. } catch (ArgumentException) {
  688. // IronPython can throw here if it can't figure out the
  689. // path of the assembly this type is defined in.
  690. return "";
  691. }
  692. });
  693. }
  694. /// <summary>
  695. /// Returns an ObjectIdentityHandle which contains a PythonType
  696. /// </summary>
  697. internal ObjectIdentityHandle GetFieldType(ObjectIdentityHandle field) {
  698. return CallAndHandle(() => {
  699. var value = (ReflectedField)Unwrap(field);
  700. return MakeHandle(value.FieldType);
  701. });
  702. }
  703. internal bool IsFieldStatic(ObjectIdentityHandle field) {
  704. return CallAndHandle(() => {
  705. var value = (ReflectedField)Unwrap(field);
  706. return value.Info.IsStatic;
  707. }, false);
  708. }
  709. #endregion
  710. #region BuiltinFunction Helpers
  711. internal string GetBuiltinFunctionName(ObjectIdentityHandle function) {
  712. return CallAndHandle(() => {
  713. BuiltinFunction func = (BuiltinFunction)Unwrap(function);
  714. return func.__name__;
  715. });
  716. }
  717. internal string GetBuiltinFunctionDocumentation(ObjectIdentityHandle function) {
  718. return CallAndHandle(() => {
  719. BuiltinFunction func = (BuiltinFunction)Unwrap(function);
  720. try {
  721. return func.__doc__;
  722. } catch (ArgumentException) {
  723. // IronPython can throw here if it can't figure out the
  724. // path of the assembly this type is defined in.
  725. return "";
  726. }
  727. });
  728. }
  729. internal string GetBuiltinFunctionModule(ObjectIdentityHandle function) {
  730. return CallAndHandle(() => {
  731. BuiltinFunction func = (BuiltinFunction)Unwrap(function);
  732. return func.Get__module__(CodeContext);
  733. });
  734. }
  735. internal ObjectIdentityHandle GetBuiltinFunctionDeclaringPythonType(ObjectIdentityHandle function) {
  736. return CallAndHandle(() => {
  737. BuiltinFunction func = (BuiltinFunction)Unwrap(function);
  738. return MakeHandle(DynamicHelpers.GetPythonTypeFromType(func.DeclaringType));
  739. });
  740. }
  741. internal ObjectIdentityHandle[] GetBuiltinFunctionOverloads(ObjectIdentityHandle function) {
  742. return CallAndHandle(() => {
  743. BuiltinFunction func = (BuiltinFunction)Unwrap(function);
  744. var result = new List<ObjectIdentityHandle>();
  745. foreach (var ov in func.Overloads.Functions) {
  746. BuiltinFunction overload = (ov as BuiltinFunction);
  747. if (overload.Overloads.Targets[0].DeclaringType.IsAssignableFrom(func.DeclaringType) ||
  748. (overload.Overloads.Targets[0].DeclaringType.FullName != null &&
  749. overload.Overloads.Targets[0].DeclaringType.FullName.StartsWith("IronPython.Runtime.Operations."))) {
  750. result.Add(MakeHandle(overload.Targets[0]));
  751. }
  752. }
  753. return result.ToArray();
  754. }, () => new ObjectIdentityHandle[0]);
  755. }
  756. internal ObjectIdentityHandle[] GetConstructorFunctionTargets(ObjectIdentityHandle function) {
  757. return CallAndHandle(() => {
  758. return ((ConstructorFunction)Unwrap(function)).Overloads.Targets
  759. .Select(x => MakeHandle(x))
  760. .ToArray();
  761. }, () => Array.Empty<ObjectIdentityHandle>());
  762. }
  763. internal ObjectIdentityHandle GetConstructorFunctionDeclaringType(ObjectIdentityHandle function) {
  764. return CallAndHandle(() =>
  765. MakeHandle(
  766. GetTypeFromType(
  767. ((ConstructorFunction)Unwrap(function)).Overloads.Targets
  768. .First()
  769. .DeclaringType
  770. )
  771. )
  772. );
  773. }
  774. #endregion
  775. #region ReflectedProperty Helpers
  776. internal ObjectIdentityHandle GetPropertyType(ObjectIdentityHandle property) {
  777. return CallAndHandle(() => {
  778. ReflectedProperty prop = (ReflectedProperty)Unwrap(property);
  779. return MakeHandle(prop.PropertyType);
  780. });
  781. }
  782. internal bool IsPropertyStatic(ObjectIdentityHandle property) {
  783. return CallAndHandle(() => {
  784. ReflectedProperty prop = (ReflectedProperty)Unwrap(property);
  785. var method = prop.Info.GetGetMethod() ?? prop.Info.GetSetMethod();
  786. if (method != null) {
  787. return method.IsStatic;
  788. }
  789. return false;
  790. }, false);
  791. }
  792. internal string GetPropertyDocumentation(ObjectIdentityHandle property) {
  793. return CallAndHandle(() => {
  794. ReflectedProperty prop = (ReflectedProperty)Unwrap(property);
  795. try {
  796. return prop.__doc__;
  797. } catch (ArgumentException) {
  798. // IronPython can throw here if it can't figure out the
  799. // path of the assembly this type is defined in.
  800. return "";
  801. }
  802. });
  803. }
  804. #endregion
  805. #region Object Helpers
  806. internal ObjectIdentityHandle GetObjectPythonType(ObjectIdentityHandle value) {
  807. return CallAndHandle(() => {
  808. return MakeHandle(DynamicHelpers.GetPythonType(Unwrap(value)));
  809. });
  810. }
  811. internal bool IsEnumValue(ObjectIdentityHandle value) {
  812. return CallAndHandle(() => {
  813. var obj = Unwrap(value).GetType();
  814. return obj.IsEnum;
  815. }, false);
  816. }
  817. internal ObjectIdentityHandle GetMember(ObjectIdentityHandle from, string name) {
  818. return CallAndHandle(() => {
  819. var obj = Unwrap(from);
  820. PythonType pyType = (obj as PythonType);
  821. if (pyType != null) {
  822. foreach (var baseType in pyType.mro()) {
  823. PythonType curType = (baseType as PythonType);
  824. if (curType != null) {
  825. IDictionary<object, object> dict = new DictProxy(curType);
  826. object bresult;
  827. // reflection can throw while resolving references, ignore the member...
  828. // http://pytools.codeplex.com/workitem/612
  829. try {
  830. if (dict.TryGetValue(name, out bresult)) {
  831. return MakeHandle(bresult);
  832. }
  833. } catch {
  834. }
  835. }
  836. }
  837. }
  838. var tracker = obj as NamespaceTracker;
  839. if (tracker != null) {
  840. object value = NamespaceTrackerOps.GetCustomMember(CodeContext, tracker, name);
  841. if (value != OperationFailed.Value) {
  842. return MakeHandle(value);
  843. } else {
  844. return MakeHandle(obj);
  845. }
  846. }
  847. object result;
  848. if (TryGetMember(obj, name, true, out result)) {
  849. return MakeHandle(result);
  850. }
  851. return MakeHandle(obj);
  852. });
  853. }
  854. #endregion
  855. #region ReflectedEvent Helpers
  856. internal string GetEventDocumentation(ObjectIdentityHandle value) {
  857. return CallAndHandle(() => {
  858. var eventObj = (ReflectedEvent)Unwrap(value);
  859. try {
  860. return eventObj.__doc__;
  861. } catch (ArgumentException) {
  862. // IronPython can throw here if it can't figure out the
  863. // path of the assembly this type is defined in.
  864. return "";
  865. }
  866. });
  867. }
  868. internal ObjectIdentityHandle GetEventPythonType(ObjectIdentityHandle value) {
  869. return CallAndHandle(() => {
  870. var eventObj = (ReflectedEvent)Unwrap(value);
  871. return MakeHandle(DynamicHelpers.GetPythonTypeFromType(eventObj.Info.EventHandlerType));
  872. });
  873. }
  874. internal ObjectIdentityHandle[] GetEventParameterPythonTypes(ObjectIdentityHandle value) {
  875. return CallAndHandle(() => {
  876. var eventObj = (ReflectedEvent)Unwrap(value);
  877. var parameters = eventObj.Info.EventHandlerType.GetMethod("Invoke").GetParameters();
  878. var res = new ObjectIdentityHandle[parameters.Length];
  879. for (int i = 0; i < parameters.Length; i++) {
  880. res[i] = MakeHandle(DynamicHelpers.GetPythonTypeFromType(parameters[i].ParameterType));
  881. }
  882. return res;
  883. }, () => new ObjectIdentityHandle[0]);
  884. }
  885. #endregion
  886. #region NamespaceTracker Helpers
  887. internal string GetNamespaceName(ObjectIdentityHandle ns) {
  888. return CallAndHandle(() => {
  889. var reflNs = (NamespaceTracker)Unwrap(ns);
  890. return reflNs.Name;
  891. });
  892. }
  893. internal string[] GetNamespaceChildren(ObjectIdentityHandle ns) {
  894. return CallAndHandle(() => {
  895. List<string> names = new List<string>();
  896. var reflNs = (NamespaceTracker)Unwrap(ns);
  897. foreach (var name in reflNs.GetMemberNames() ?? Enumerable.Empty<string>()) {
  898. if (reflNs[name] is NamespaceTracker) {
  899. names.Add(name);
  900. }
  901. }
  902. return names.ToArray();
  903. });
  904. }
  905. #endregion
  906. #region TypeGroup Helpers
  907. internal bool TypeGroupHasNewOrInitMethods(ObjectIdentityHandle typeGroup) {
  908. return CallAndHandle(() => {
  909. var value = (TypeGroup)Unwrap(typeGroup);
  910. foreach (var type in value.Types) {
  911. if (PythonTypeHasNewOrInitMethods(DynamicHelpers.GetPythonTypeFromType(type))) {
  912. return true;
  913. }
  914. }
  915. return false;
  916. }, false);
  917. }
  918. internal ObjectIdentityHandle TypeGroupMakeGenericType(ObjectIdentityHandle typeGroup, ObjectIdentityHandle[] types) {
  919. return CallAndHandle(() => {
  920. var value = (TypeGroup)Unwrap(typeGroup);
  921. var genType = value.GetTypeForArity(types.Length);
  922. if (genType != null) {
  923. Type[] genTypes = new Type[types.Length];
  924. for (int i = 0; i < types.Length; i++) {
  925. var o = Unwrap(types[i]);
  926. genTypes[i] = o as Type ?? (PythonType)o;
  927. }
  928. return MakeHandle(DynamicHelpers.GetPythonTypeFromType(genType.Type.MakeGenericType(genTypes)));
  929. }
  930. return new ObjectIdentityHandle();
  931. });
  932. }
  933. internal bool TypeGroupIsGenericTypeDefinition(ObjectIdentityHandle typeGroup) {
  934. return CallAndHandle(() => {
  935. var value = (TypeGroup)Unwrap(typeGroup);
  936. foreach (var type in value.Types) {
  937. if (type.IsGenericTypeDefinition) {
  938. return true;
  939. }
  940. }
  941. return false;
  942. }, false);
  943. }
  944. internal string GetTypeGroupDocumentation(ObjectIdentityHandle typeGroup) {
  945. return CallAndHandle(() => {
  946. var value = (TypeGroup)Unwrap(typeGroup);
  947. StringBuilder res = new StringBuilder();
  948. foreach (var type in value.Types) {
  949. try {
  950. res.Append(PythonType.Get__doc__(CodeContext, DynamicHelpers.GetPythonTypeFromType(type)) as string);
  951. } catch (ArgumentException) {
  952. // IronPython can throw here if it can't figure out the
  953. // path of the assembly this type is defined in.
  954. }
  955. }
  956. return res.ToString();
  957. });
  958. }
  959. internal string GetTypeGroupName(ObjectIdentityHandle typeGroup) {
  960. return CallAndHandle(() => {
  961. var value = (TypeGroup)Unwrap(typeGroup);
  962. return value.Name;
  963. });
  964. }
  965. internal string GetTypeGroupDeclaringModule(ObjectIdentityHandle typeGroup) {
  966. return CallAndHandle(() => {
  967. var value = (TypeGroup)Unwrap(typeGroup);
  968. return (string)PythonType.Get__module__(
  969. CodeContext,
  970. DynamicHelpers.GetPythonTypeFromType(value.Types.First())
  971. );
  972. });
  973. }
  974. internal PythonMemberType GetTypeGroupMemberType(ObjectIdentityHandle typeGroup) {
  975. return CallAndHandle(() => {
  976. var value = (TypeGroup)Unwrap(typeGroup);
  977. foreach (var type in value.Types) {
  978. if (type.IsEnum) {
  979. return PythonMemberType.Enum;
  980. } else if (typeof(Delegate).IsAssignableFrom(type)) {
  981. return PythonMemberType.Delegate;
  982. }
  983. }
  984. return PythonMemberType.Class;
  985. }, PythonMemberType.Class);
  986. }
  987. internal ObjectIdentityHandle[] GetTypeGroupConstructors(ObjectIdentityHandle typeGroup, out ObjectIdentityHandle declaringType) {
  988. var innerDeclaringType = new ObjectIdentityHandle();
  989. declaringType = new ObjectIdentityHandle();
  990. var result = CallAndHandle(() => {
  991. var self = (TypeGroup)Unwrap(typeGroup);
  992. foreach (var clrType in self.Types) {
  993. // just a normal .NET type...
  994. var ctors = clrType.GetConstructors(BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance);
  995. if (ctors.Length > 0) {
  996. var res = new ObjectIdentityHandle[ctors.Length];
  997. for (int i = 0; i < res.Length; i++) {
  998. res[i] = MakeHandle(ctors[i]);
  999. }
  1000. innerDeclaringType = MakeHandle(clrType);
  1001. return res;
  1002. }
  1003. }
  1004. innerDeclaringType = default(ObjectIdentityHandle);
  1005. return null;
  1006. }, (ObjectIdentityHandle[])null);
  1007. declaringType = innerDeclaringType;
  1008. return result;
  1009. }
  1010. internal ObjectIdentityHandle[] GetTypeGroupEventInvokeArgs(ObjectIdentityHandle typeGroup) {
  1011. return CallAndHandle(() => {
  1012. var self = (TypeGroup)Unwrap(typeGroup);
  1013. foreach (var type in self.Types) {
  1014. if (typeof(Delegate).IsAssignableFrom(type)) {
  1015. return GetEventInvokeArgs(type);
  1016. }
  1017. }
  1018. return null;
  1019. }, (ObjectIdentityHandle[])null);
  1020. }
  1021. #endregion
  1022. #region ReflectedExtensionProperty Helpers
  1023. internal ObjectIdentityHandle GetExtensionPropertyType(ObjectIdentityHandle value) {
  1024. return CallAndHandle(() => {
  1025. var property = (ReflectedExtensionProperty)Unwrap(value);
  1026. return MakeHandle(property.PropertyType);
  1027. });
  1028. }
  1029. internal string GetExtensionPropertyDocumentation(ObjectIdentityHandle value) {
  1030. return CallAndHandle(() => {
  1031. var property = (ReflectedExtensionProperty)Unwrap(value);
  1032. try {
  1033. return property.__doc__;
  1034. } catch (ArgumentException) {
  1035. // IronPython can throw here if it can't figure out the
  1036. // path of the assembly this type is defined in.
  1037. return "";
  1038. }
  1039. });
  1040. }
  1041. #endregion
  1042. internal PythonType GetTypeFromType(Type type) {
  1043. if (type.IsGenericParameter && type.GetInterfaces().Length != 0) {
  1044. // generic parameter with constraints, IronPython will throw an
  1045. // exception while constructing the PythonType
  1046. // http://ironpython.codeplex.com/workitem/30905
  1047. // Return the type for the interface
  1048. return GetTypeFromType(type.GetInterfaces()[0]);
  1049. }
  1050. return DynamicHelpers.GetPythonTypeFromType(type);
  1051. }
  1052. internal ObjectIdentityHandle GetBuiltinType(BuiltinTypeId id) {
  1053. return CallAndHandle(() => {
  1054. switch (id) {
  1055. case BuiltinTypeId.Bool: return MakeHandle(GetTypeFromType(typeof(bool)));
  1056. case BuiltinTypeId.BuiltinFunction: return MakeHandle(GetTypeFromType(typeof(BuiltinFunction)));
  1057. case BuiltinTypeId.BuiltinMethodDescriptor: return MakeHandle(GetTypeFromType(typeof(BuiltinMethodDescriptor)));
  1058. case BuiltinTypeId.Complex: return MakeHandle(GetTypeFromType(typeof(Complex)));
  1059. case BuiltinTypeId.Dict: return MakeHandle(GetTypeFromType(typeof(PythonDictionary)));
  1060. case BuiltinTypeId.Float: return MakeHandle(GetTypeFromType(typeof(double)));
  1061. case BuiltinTypeId.Function: return MakeHandle(GetTypeFromType(typeof(PythonFunction)));