| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 638dc1c commit 5d28a8d
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,6 +14,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. | |||
| 14 | 14 | - Added support for Jetson Nano. | |
| 15 | 15 | - Added support for __len__ for .NET classes that implement ICollection | |
| 16 | 16 | - Added `object.GetRawPythonProxy() -> PyObject` extension method, that bypasses any conversions | |
| 17 | + - Added PythonException.Format method to format exceptions the same as traceback.format_exception | ||
| 17 | 18 | ||
| 18 | 19 | ### Changed | |
| 19 | 20 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -54,5 +54,41 @@ public void TestPythonErrorTypeName() | |||
| 54 | 54 | Assert.That(ex.PythonTypeName, Is.EqualTo("ModuleNotFoundError").Or.EqualTo("ImportError")); | |
| 55 | 55 | } | |
| 56 | 56 | } | |
| 57 | + | ||
| 58 | + [Test] | ||
| 59 | + public void TestPythonExceptionFormat() | ||
| 60 | + { | ||
| 61 | + try | ||
| 62 | + { | ||
| 63 | + PythonEngine.Exec("raise ValueError('Error!')"); | ||
| 64 | + Assert.Fail("Exception should have been raised"); | ||
| 65 | + } | ||
| 66 | + catch (PythonException ex) | ||
| 67 | + { | ||
| 68 | + Assert.That(ex.Format(), Does.Contain("Traceback").And.Contains("(most recent call last):").And.Contains("ValueError: Error!")); | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + [Test] | ||
| 73 | + public void TestPythonExceptionFormatNoError() | ||
| 74 | + { | ||
| 75 | + var ex = new PythonException(); | ||
| 76 | + Assert.AreEqual(ex.StackTrace, ex.Format()); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + [Test] | ||
| 80 | + public void TestPythonExceptionFormatNoTraceback() | ||
| 81 | + { | ||
| 82 | + try | ||
| 83 | + { | ||
| 84 | + var module = PythonEngine.ImportModule("really____unknown___module"); | ||
| 85 | + Assert.Fail("Unknown module should not be loaded"); | ||
| 86 | + } | ||
| 87 | + catch (PythonException ex) | ||
| 88 | + { | ||
| 89 | + // ImportError/ModuleNotFoundError do not have a traceback when not running in a script | ||
| 90 | + Assert.AreEqual(ex.StackTrace, ex.Format()); | ||
| 91 | + } | ||
| 92 | + } | ||
| 57 | 93 | } | |
| 58 | 94 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,6 @@ | |||
| 1 | 1 | using System; | |
| 2 | 2 | using System.Runtime.CompilerServices; | |
| 3 | + using System.Text; | ||
| 3 | 4 | ||
| 4 | 5 | namespace Python.Runtime | |
| 5 | 6 | { | |
@@ -145,6 +146,47 @@ public string PythonTypeName | |||
| 145 | 146 | get { return _pythonTypeName; } | |
| 146 | 147 | } | |
| 147 | 148 | ||
| 149 | + /// <summary> | ||
| 150 | + /// Formats this PythonException object into a message as would be printed | ||
| 151 | + /// out via the Python console. See traceback.format_exception | ||
| 152 | + /// </summary> | ||
| 153 | + public string Format() | ||
| 154 | + { | ||
| 155 | + string res; | ||
| 156 | + IntPtr gs = PythonEngine.AcquireLock(); | ||
| 157 | + try | ||
| 158 | + { | ||
| 159 | + if (_pyTB != IntPtr.Zero && _pyType != IntPtr.Zero && _pyValue != IntPtr.Zero) | ||
| 160 | + { | ||
| 161 | + Runtime.XIncref(_pyType); | ||
| 162 | + Runtime.XIncref(_pyValue); | ||
| 163 | + Runtime.XIncref(_pyTB); | ||
| 164 | + using (PyObject pyType = new PyObject(_pyType)) | ||
| 165 | + using (PyObject pyValue = new PyObject(_pyValue)) | ||
| 166 | + using (PyObject pyTB = new PyObject(_pyTB)) | ||
| 167 | + using (PyObject tb_mod = PythonEngine.ImportModule("traceback")) | ||
| 168 | + { | ||
| 169 | + var buffer = new StringBuilder(); | ||
| 170 | + var values = tb_mod.InvokeMethod("format_exception", pyType, pyValue, pyTB); | ||
| 171 | + foreach (PyObject val in values) | ||
| 172 | + { | ||
| 173 | + buffer.Append(val.ToString()); | ||
| 174 | + } | ||
| 175 | + res = buffer.ToString(); | ||
| 176 | + } | ||
| 177 | + } | ||
| 178 | + else | ||
| 179 | + { | ||
| 180 | + res = StackTrace; | ||
| 181 | + } | ||
| 182 | + } | ||
| 183 | + finally | ||
| 184 | + { | ||
| 185 | + PythonEngine.ReleaseLock(gs); | ||
| 186 | + } | ||
| 187 | + return res; | ||
| 188 | + } | ||
| 189 | + | ||
| 148 | 190 | /// <summary> | |
| 149 | 191 | /// Dispose Method | |
| 150 | 192 | /// </summary> | |
| Back | FazBrowse Home | New Git URL |
0 commit comments