PythonTestCases()
+ {
+ // Add the test that you want to debug here.
+ yield return new[] { "test_enum", "test_enum_standard_attrs" };
+ yield return new[] { "test_generic", "test_missing_generic_type" };
+ }
+
+ ///
+ /// Runs a test in src/tests/*.py as an embedded test. This facilitates debugging.
+ ///
+ /// The file name without extension
+ /// The name of the test method
+ [TestCaseSource(nameof(PythonTestCases))]
+ public void RunPythonTest(string testFile, string testName)
+ {
+ // Find the tests directory
+ string folder = typeof(PythonTestRunner).Assembly.Location;
+ while (Path.GetFileName(folder) != "src")
+ {
+ folder = Path.GetDirectoryName(folder);
+ }
+ folder = Path.Combine(folder, "tests");
+ string path = Path.Combine(folder, testFile + ".py");
+ if (!File.Exists(path)) throw new FileNotFoundException("Cannot find test file", path);
+
+ // We could use 'import' below, but importlib gives more helpful error messages than 'import'
+ // https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
+ // Because the Python tests sometimes have relative imports, the module name must be inside the tests package
+ PythonEngine.Exec($@"
+import sys
+import os
+sys.path.append(os.path.dirname(r'{folder}'))
+sys.path.append(os.path.join(r'{folder}', 'fixtures'))
+import clr
+clr.AddReference('Python.Test')
+import tests
+module_name = 'tests.{testFile}'
+file_path = r'{path}'
+import importlib.util
+spec = importlib.util.spec_from_file_location(module_name, file_path)
+module = importlib.util.module_from_spec(spec)
+sys.modules[module_name] = module
+try:
+ spec.loader.exec_module(module)
+except ImportError as error:
+ raise ImportError(str(error) + ' when sys.path=' + os.pathsep.join(sys.path))
+module.{testName}()
+");
+ }
+ }
+}
diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs
index d8f7e4dcc..af6174188 100644
--- a/src/runtime/importhook.cs
+++ b/src/runtime/importhook.cs
@@ -291,6 +291,8 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
// We don't support them anyway
return IntPtr.Zero;
}
+ // Save the exception
+ var originalException = new PythonException();
// Otherwise, just clear the it.
Exceptions.Clear();
@@ -342,7 +344,7 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
ManagedType mt = tail.GetAttribute(name, true);
if (!(mt is ModuleObject))
{
- Exceptions.SetError(Exceptions.ImportError, $"No module named {name}");
+ originalException.Restore();
return IntPtr.Zero;
}
if (head == null)
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy