| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9fd877e commit 4e1ea84
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -38,8 +38,8 @@ public void SetUp() | |||
| 38 | 38 | string testPath = Path.Combine(TestContext.CurrentContext.TestDirectory, s); | |
| 39 | 39 | ||
| 40 | 40 | IntPtr str = Runtime.Runtime.PyString_FromString(testPath); | |
| 41 | - IntPtr path = Runtime.Runtime.PySys_GetObject("path"); | ||
| 42 | - Runtime.Runtime.PyList_Append(new BorrowedReference(path), str); | ||
| 41 | + BorrowedReference path = Runtime.Runtime.PySys_GetObject("path"); | ||
| 42 | + Runtime.Runtime.PyList_Append(path, str); | ||
| 43 | 43 | } | |
| 44 | 44 | ||
| 45 | 45 | [TearDown] | |
@@ -83,5 +83,28 @@ public void TestCastGlobalVar() | |||
| 83 | 83 | Assert.AreEqual("2", foo.FOO.ToString()); | |
| 84 | 84 | Assert.AreEqual("2", foo.test_foo().ToString()); | |
| 85 | 85 | } | |
| 86 | + | ||
| 87 | + [Test] | ||
| 88 | + public void BadAssembly() | ||
| 89 | + { | ||
| 90 | + string path; | ||
| 91 | + if (Python.Runtime.Runtime.IsWindows) | ||
| 92 | + { | ||
| 93 | + path = @"C:\Windows\System32\kernel32.dll"; | ||
| 94 | + } | ||
| 95 | + else | ||
| 96 | + { | ||
| 97 | + Assert.Pass("TODO: add bad assembly location for other platforms"); | ||
| 98 | + return; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + string code = $@" | ||
| 102 | + import clr | ||
| 103 | + clr.AddReference('{path}') | ||
| 104 | + "; | ||
| 105 | + | ||
| 106 | + var error = Assert.Throws<PythonException>(() => PythonEngine.Exec(code)); | ||
| 107 | + Assert.AreEqual(nameof(FileLoadException), error.PythonTypeName); | ||
| 108 | + } | ||
| 86 | 109 | } | |
| 87 | 110 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -137,7 +137,7 @@ private static Assembly ResolveHandler(object ob, ResolveEventArgs args) | |||
| 137 | 137 | /// </summary> | |
| 138 | 138 | internal static void UpdatePath() | |
| 139 | 139 | { | |
| 140 | - IntPtr list = Runtime.PySys_GetObject("path"); | ||
| 140 | + BorrowedReference list = Runtime.PySys_GetObject("path"); | ||
| 141 | 141 | var count = Runtime.PyList_Size(list); | |
| 142 | 142 | if (count != pypath.Count) | |
| 143 | 143 | { | |
@@ -199,19 +199,14 @@ public static string FindAssembly(string name) | |||
| 199 | 199 | /// </summary> | |
| 200 | 200 | public static Assembly LoadAssembly(string name) | |
| 201 | 201 | { | |
| 202 | - Assembly assembly = null; | ||
| 203 | 202 | try | |
| 204 | 203 | { | |
| 205 | - assembly = Assembly.Load(name); | ||
| 204 | + return Assembly.Load(name); | ||
| 206 | 205 | } | |
| 207 | - catch (Exception) | ||
| 206 | + catch (FileNotFoundException) | ||
| 208 | 207 | { | |
| 209 | - //if (!(e is System.IO.FileNotFoundException)) | ||
| 210 | - //{ | ||
| 211 | - // throw; | ||
| 212 | - //} | ||
| 208 | + return null; | ||
| 213 | 209 | } | |
| 214 | - return assembly; | ||
| 215 | 210 | } | |
| 216 | 211 | ||
| 217 | 212 | ||
@@ -221,18 +216,8 @@ public static Assembly LoadAssembly(string name) | |||
| 221 | 216 | public static Assembly LoadAssemblyPath(string name) | |
| 222 | 217 | { | |
| 223 | 218 | string path = FindAssembly(name); | |
| 224 | - Assembly assembly = null; | ||
| 225 | - if (path != null) | ||
| 226 | - { | ||
| 227 | - try | ||
| 228 | - { | ||
| 229 | - assembly = Assembly.LoadFrom(path); | ||
| 230 | - } | ||
| 231 | - catch (Exception) | ||
| 232 | - { | ||
| 233 | - } | ||
| 234 | - } | ||
| 235 | - return assembly; | ||
| 219 | + if (path == null) return null; | ||
| 220 | + return Assembly.LoadFrom(path); | ||
| 236 | 221 | } | |
| 237 | 222 | ||
| 238 | 223 | /// <summary> | |
@@ -242,25 +227,18 @@ public static Assembly LoadAssemblyPath(string name) | |||
| 242 | 227 | /// <returns></returns> | |
| 243 | 228 | public static Assembly LoadAssemblyFullPath(string name) | |
| 244 | 229 | { | |
| 245 | - Assembly assembly = null; | ||
| 246 | 230 | if (Path.IsPathRooted(name)) | |
| 247 | 231 | { | |
| 248 | - if (!Path.HasExtension(name)) | ||
| 232 | + if (!Path.HasExtension(name) && Runtime.InteropVersion < new Version(3, 0)) | ||
| 249 | 233 | { | |
| 250 | 234 | name = name + ".dll"; | |
| 251 | 235 | } | |
| 252 | 236 | if (File.Exists(name)) | |
| 253 | 237 | { | |
| 254 | - try | ||
| 255 | - { | ||
| 256 | - assembly = Assembly.LoadFrom(name); | ||
| 257 | - } | ||
| 258 | - catch (Exception) | ||
| 259 | - { | ||
| 260 | - } | ||
| 238 | + return Assembly.LoadFrom(name); | ||
| 261 | 239 | } | |
| 262 | 240 | } | |
| 263 | - return assembly; | ||
| 241 | + return null; | ||
| 264 | 242 | } | |
| 265 | 243 | ||
| 266 | 244 | /// <summary> | |
@@ -291,7 +269,7 @@ public static Assembly FindLoadedAssembly(string name) | |||
| 291 | 269 | /// actually loads an assembly. | |
| 292 | 270 | /// Call ONLY for namespaces that HAVE NOT been cached yet. | |
| 293 | 271 | /// </remarks> | |
| 294 | - public static bool LoadImplicit(string name, bool warn = true) | ||
| 272 | + public static bool LoadImplicit(string name, Action<Exception> assemblyLoadErrorHandler, bool warn = true) | ||
| 295 | 273 | { | |
| 296 | 274 | string[] names = name.Split('.'); | |
| 297 | 275 | var loaded = false; | |
@@ -308,14 +286,23 @@ public static bool LoadImplicit(string name, bool warn = true) | |||
| 308 | 286 | assembliesSet = new HashSet<Assembly>(AppDomain.CurrentDomain.GetAssemblies()); | |
| 309 | 287 | } | |
| 310 | 288 | Assembly a = FindLoadedAssembly(s); | |
| 311 | - if (a == null) | ||
| 312 | - { | ||
| 313 | - a = LoadAssemblyPath(s); | ||
| 314 | - } | ||
| 315 | - if (a == null) | ||
| 289 | + try | ||
| 316 | 290 | { | |
| 317 | - a = LoadAssembly(s); | ||
| 291 | + if (a == null) | ||
| 292 | + { | ||
| 293 | + a = LoadAssemblyPath(s); | ||
| 294 | + } | ||
| 295 | + | ||
| 296 | + if (a == null) | ||
| 297 | + { | ||
| 298 | + a = LoadAssembly(s); | ||
| 299 | + } | ||
| 318 | 300 | } | |
| 301 | + catch (FileLoadException e) { assemblyLoadErrorHandler(e); } | ||
| 302 | + catch (BadImageFormatException e) { assemblyLoadErrorHandler(e); } | ||
| 303 | + catch (System.Security.SecurityException e) { assemblyLoadErrorHandler(e); } | ||
| 304 | + catch (PathTooLongException e) { assemblyLoadErrorHandler(e); } | ||
| 305 | + | ||
| 319 | 306 | if (a != null && !assembliesSet.Contains(a)) | |
| 320 | 307 | { | |
| 321 | 308 | loaded = true; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -256,9 +256,9 @@ public static void SetError(IntPtr ob, string value) | |||
| 256 | 256 | /// Sets the current Python exception given a Python object. | |
| 257 | 257 | /// This is a wrapper for the Python PyErr_SetObject call. | |
| 258 | 258 | /// </remarks> | |
| 259 | - public static void SetError(IntPtr ob, IntPtr value) | ||
| 259 | + public static void SetError(IntPtr type, IntPtr exceptionObject) | ||
| 260 | 260 | { | |
| 261 | - Runtime.PyErr_SetObject(ob, value); | ||
| 261 | + Runtime.PyErr_SetObject(new BorrowedReference(type), new BorrowedReference(exceptionObject)); | ||
| 262 | 262 | } | |
| 263 | 263 | ||
| 264 | 264 | /// <summary> | |
@@ -288,7 +288,7 @@ public static void SetError(Exception e) | |||
| 288 | 288 | ||
| 289 | 289 | IntPtr op = CLRObject.GetInstHandle(e); | |
| 290 | 290 | IntPtr etype = Runtime.PyObject_GetAttrString(op, "__class__"); | |
| 291 | - Runtime.PyErr_SetObject(etype, op); | ||
| 291 | + Runtime.PyErr_SetObject(new BorrowedReference(etype), new BorrowedReference(op)); | ||
| 292 | 292 | Runtime.XDecref(etype); | |
| 293 | 293 | Runtime.XDecref(op); | |
| 294 | 294 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Collections.Generic; | ||
| 2 | 3 | using System.Runtime.InteropServices; | |
| 3 | 4 | ||
| 4 | 5 | namespace Python.Runtime | |
@@ -238,22 +239,12 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) | |||
| 238 | 239 | // Check these BEFORE the built-in import runs; may as well | |
| 239 | 240 | // do the Incref()ed return here, since we've already found | |
| 240 | 241 | // the module. | |
| 241 | - if (mod_name == "clr") | ||
| 242 | + if (mod_name == "clr" || mod_name == "CLR") | ||
| 242 | 243 | { | |
| 243 | - IntPtr clr_module = GetCLRModule(fromList); | ||
| 244 | - if (clr_module != IntPtr.Zero) | ||
| 244 | + if (mod_name == "CLR") | ||
| 245 | 245 | { | |
| 246 | - IntPtr sys_modules = Runtime.PyImport_GetModuleDict(); | ||
| 247 | - if (sys_modules != IntPtr.Zero) | ||
| 248 | - { | ||
| 249 | - Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module); | ||
| 250 | - } | ||
| 246 | + Exceptions.deprecation("The CLR module is deprecated. Please use 'clr'."); | ||
| 251 | 247 | } | |
| 252 | - return clr_module; | ||
| 253 | - } | ||
| 254 | - if (mod_name == "CLR") | ||
| 255 | - { | ||
| 256 | - Exceptions.deprecation("The CLR module is deprecated. Please use 'clr'."); | ||
| 257 | 248 | IntPtr clr_module = GetCLRModule(fromList); | |
| 258 | 249 | if (clr_module != IntPtr.Zero) | |
| 259 | 250 | { | |
@@ -265,9 +256,10 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) | |||
| 265 | 256 | } | |
| 266 | 257 | return clr_module; | |
| 267 | 258 | } | |
| 259 | + | ||
| 268 | 260 | string realname = mod_name; | |
| 269 | 261 | string clr_prefix = null; | |
| 270 | - if (mod_name.StartsWith("CLR.")) | ||
| 262 | + if (mod_name.StartsWith("CLR.") && Runtime.InteropVersion < new Version(3,0)) | ||
| 271 | 263 | { | |
| 272 | 264 | clr_prefix = "CLR."; // prepend when adding the module to sys.modules | |
| 273 | 265 | realname = mod_name.Substring(4); | |
@@ -328,11 +320,22 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) | |||
| 328 | 320 | AssemblyManager.UpdatePath(); | |
| 329 | 321 | if (!AssemblyManager.IsValidNamespace(realname)) | |
| 330 | 322 | { | |
| 331 | - if (!AssemblyManager.LoadImplicit(realname)) | ||
| 323 | + var loadExceptions = new List<Exception>(); | ||
| 324 | + if (!AssemblyManager.LoadImplicit(realname, assemblyLoadErrorHandler: loadExceptions.Add)) | ||
| 332 | 325 | { | |
| 333 | 326 | // May be called when a module being imported imports a module. | |
| 334 | 327 | // In particular, I've seen decimal import copy import org.python.core | |
| 335 | - return Runtime.PyObject_Call(py_import, args, kw); | ||
| 328 | + IntPtr importResult = Runtime.PyObject_Call(py_import, args, kw); | ||
| 329 | + // TODO: use ModuleNotFoundError in Python 3.6+ | ||
| 330 | + if (importResult == IntPtr.Zero && loadExceptions.Count > 0 | ||
| 331 | + && Exceptions.ExceptionMatches(Exceptions.ImportError)) | ||
| 332 | + { | ||
| 333 | + loadExceptions.Add(new PythonException()); | ||
| 334 | + var importError = new PyObject(new BorrowedReference(Exceptions.ImportError)); | ||
| 335 | + importError.SetAttr("__cause__", new AggregateException(loadExceptions).ToPython()); | ||
| 336 | + Runtime.PyErr_SetObject(new BorrowedReference(Exceptions.ImportError), importError.Reference); | ||
| 337 | + } | ||
| 338 | + return importResult; | ||
| 336 | 339 | } | |
| 337 | 340 | } | |
| 338 | 341 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -291,8 +291,8 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth | |||
| 291 | 291 | IntPtr valueList = Runtime.PyDict_Values(kw); | |
| 292 | 292 | for (int i = 0; i < pynkwargs; ++i) | |
| 293 | 293 | { | |
| 294 | - var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(keylist, i)); | ||
| 295 | - kwargDict[keyStr] = Runtime.PyList_GetItem(valueList, i).DangerousGetAddress(); | ||
| 294 | + var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i)); | ||
| 295 | + kwargDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress(); | ||
| 296 | 296 | } | |
| 297 | 297 | Runtime.XDecref(keylist); | |
| 298 | 298 | Runtime.XDecref(valueList); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -119,7 +119,7 @@ public ManagedType GetAttribute(string name, bool guess) | |||
| 119 | 119 | // cost. Ask the AssemblyManager to do implicit loading for each | |
| 120 | 120 | // of the steps in the qualified name, then try it again. | |
| 121 | 121 | bool ignore = name.StartsWith("__"); | |
| 122 | - if (AssemblyManager.LoadImplicit(qname, !ignore)) | ||
| 122 | + if (AssemblyManager.LoadImplicit(qname, assemblyLoadErrorHandler: ImportWarning, !ignore)) | ||
| 123 | 123 | { | |
| 124 | 124 | if (AssemblyManager.IsValidNamespace(qname)) | |
| 125 | 125 | { | |
@@ -161,6 +161,11 @@ public ManagedType GetAttribute(string name, bool guess) | |||
| 161 | 161 | return null; | |
| 162 | 162 | } | |
| 163 | 163 | ||
| 164 | + static void ImportWarning(Exception exception) | ||
| 165 | + { | ||
| 166 | + Exceptions.warn(exception.ToString(), Exceptions.ImportWarning); | ||
| 167 | + } | ||
| 168 | + | ||
| 164 | 169 | ||
| 165 | 170 | /// <summary> | |
| 166 | 171 | /// Stores an attribute in the instance dict for future lookups. | |
@@ -365,7 +370,7 @@ internal void InitializePreload() | |||
| 365 | 370 | if (interactive_preload) | |
| 366 | 371 | { | |
| 367 | 372 | interactive_preload = false; | |
| 368 | - if (Runtime.PySys_GetObject("ps1") != IntPtr.Zero) | ||
| 373 | + if (!Runtime.PySys_GetObject("ps1").IsNull) | ||
| 369 | 374 | { | |
| 370 | 375 | preload = true; | |
| 371 | 376 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,6 +22,11 @@ public PyList(IntPtr ptr) : base(ptr) | |||
| 22 | 22 | { | |
| 23 | 23 | } | |
| 24 | 24 | ||
| 25 | + /// <summary> | ||
| 26 | + /// Creates new <see cref="PyList"/> pointing to the same object, as the given reference. | ||
| 27 | + /// </summary> | ||
| 28 | + internal PyList(BorrowedReference reference) : base(reference) { } | ||
| 29 | + | ||
| 25 | 30 | ||
| 26 | 31 | /// <summary> | |
| 27 | 32 | /// PyList Constructor | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,6 +16,8 @@ protected PySequence(IntPtr ptr) : base(ptr) | |||
| 16 | 16 | { | |
| 17 | 17 | } | |
| 18 | 18 | ||
| 19 | + internal PySequence(BorrowedReference reference) : base(reference) { } | ||
| 20 | + | ||
| 19 | 21 | protected PySequence() | |
| 20 | 22 | { | |
| 21 | 23 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -111,6 +111,9 @@ public class Runtime | |||
| 111 | 111 | // .NET core: System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows) | |
| 112 | 112 | internal static bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; | |
| 113 | 113 | ||
| 114 | + internal static Version InteropVersion { get; } | ||
| 115 | + = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; | ||
| 116 | + | ||
| 114 | 117 | static readonly Dictionary<string, OperatingSystemType> OperatingSystemTypeMapping = new Dictionary<string, OperatingSystemType>() | |
| 115 | 118 | { | |
| 116 | 119 | { "Windows", OperatingSystemType.Windows }, | |
@@ -339,9 +342,9 @@ internal static void Initialize(bool initSigs = false) | |||
| 339 | 342 | // Need to add the runtime directory to sys.path so that we | |
| 340 | 343 | // can find built-in assemblies like System.Data, et. al. | |
| 341 | 344 | string rtdir = RuntimeEnvironment.GetRuntimeDirectory(); | |
| 342 | - IntPtr path = PySys_GetObject("path"); | ||
| 345 | + BorrowedReference path = PySys_GetObject("path"); | ||
| 343 | 346 | IntPtr item = PyString_FromString(rtdir); | |
| 344 | - PyList_Append(new BorrowedReference(path), item); | ||
| 347 | + PyList_Append(path, item); | ||
| 345 | 348 | XDecref(item); | |
| 346 | 349 | AssemblyManager.UpdatePath(); | |
| 347 | 350 | } | |
@@ -1642,13 +1645,13 @@ internal static IntPtr PyList_New(long size) | |||
| 1642 | 1645 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1643 | 1646 | internal static extern IntPtr PyList_AsTuple(IntPtr pointer); | |
| 1644 | 1647 | ||
| 1645 | - internal static BorrowedReference PyList_GetItem(IntPtr pointer, long index) | ||
| 1648 | + internal static BorrowedReference PyList_GetItem(BorrowedReference pointer, long index) | ||
| 1646 | 1649 | { | |
| 1647 | 1650 | return PyList_GetItem(pointer, new IntPtr(index)); | |
| 1648 | 1651 | } | |
| 1649 | 1652 | ||
| 1650 | 1653 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1651 | - private static extern BorrowedReference PyList_GetItem(IntPtr pointer, IntPtr index); | ||
| 1654 | + private static extern BorrowedReference PyList_GetItem(BorrowedReference pointer, IntPtr index); | ||
| 1652 | 1655 | ||
| 1653 | 1656 | internal static int PyList_SetItem(IntPtr pointer, long index, IntPtr value) | |
| 1654 | 1657 | { | |
@@ -1691,13 +1694,13 @@ internal static int PyList_SetSlice(IntPtr pointer, long start, long end, IntPtr | |||
| 1691 | 1694 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1692 | 1695 | private static extern int PyList_SetSlice(IntPtr pointer, IntPtr start, IntPtr end, IntPtr value); | |
| 1693 | 1696 | ||
| 1694 | - internal static long PyList_Size(IntPtr pointer) | ||
| 1697 | + internal static long PyList_Size(BorrowedReference pointer) | ||
| 1695 | 1698 | { | |
| 1696 | 1699 | return (long)_PyList_Size(pointer); | |
| 1697 | 1700 | } | |
| 1698 | 1701 | ||
| 1699 | 1702 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")] | |
| 1700 | - private static extern IntPtr _PyList_Size(IntPtr pointer); | ||
| 1703 | + private static extern IntPtr _PyList_Size(BorrowedReference pointer); | ||
| 1701 | 1704 | ||
| 1702 | 1705 | //==================================================================== | |
| 1703 | 1706 | // Python tuple API | |
@@ -1825,7 +1828,7 @@ int updatepath | |||
| 1825 | 1828 | #endif | |
| 1826 | 1829 | ||
| 1827 | 1830 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1828 | - internal static extern IntPtr PySys_GetObject(string name); | ||
| 1831 | + internal static extern BorrowedReference PySys_GetObject(string name); | ||
| 1829 | 1832 | ||
| 1830 | 1833 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1831 | 1834 | internal static extern int PySys_SetObject(string name, IntPtr ob); | |
@@ -1923,7 +1926,7 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) | |||
| 1923 | 1926 | internal static extern void PyErr_SetString(IntPtr ob, string message); | |
| 1924 | 1927 | ||
| 1925 | 1928 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1926 | - internal static extern void PyErr_SetObject(IntPtr ob, IntPtr message); | ||
| 1929 | + internal static extern void PyErr_SetObject(BorrowedReference type, BorrowedReference exceptionObject); | ||
| 1927 | 1930 | ||
| 1928 | 1931 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1929 | 1932 | internal static extern IntPtr PyErr_SetFromErrno(IntPtr ob); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments