-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Pythonnet's ClrBubbledException interpreter (#7523)
* Add ClrBubbleExceptionInterpreter * Add ClrBubbledExceptionInterpreter tests * Bump pythonnet version to 2.0.23 * Minor changes * Minor change * Minor fix * Fix failing unit tests
- Loading branch information
1 parent
fff037b
commit 1df11c0
Showing
22 changed files
with
229 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. | ||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
using System; | ||
using Python.Runtime; | ||
using QuantConnect.Util; | ||
|
||
namespace QuantConnect.Exceptions | ||
{ | ||
/// <summary> | ||
/// Interprets <see cref="ClrBubbledException"/> instances | ||
/// </summary> | ||
public class ClrBubbledExceptionInterpreter : SystemExceptionInterpreter | ||
{ | ||
/// <summary> | ||
/// Determines the order that an instance of this class should be called | ||
/// </summary> | ||
public override int Order => int.MaxValue - 1; | ||
|
||
/// <summary> | ||
/// Determines if this interpreter should be applied to the specified exception. f | ||
/// </summary> | ||
/// <param name="exception">The exception to check</param> | ||
/// <returns>True if the exception can be interpreted, false otherwise</returns> | ||
public override bool CanInterpret(Exception exception) => exception?.GetType() == typeof(ClrBubbledException); | ||
|
||
/// <summary> | ||
/// Interprets the specified exception into a new exception | ||
/// </summary> | ||
/// <param name="exception">The exception to be interpreted</param> | ||
/// <param name="innerInterpreter">An interpreter that should be applied to the inner exception.</param> | ||
/// <returns>The interpreted exception</returns> | ||
public override Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter) | ||
{ | ||
var pe = (ClrBubbledException)exception; | ||
var sanitized = base.Interpret(exception, innerInterpreter); | ||
var inner = sanitized.InnerException ?? sanitized; | ||
|
||
return new Exception(pe.Message + PythonUtil.PythonExceptionStackParser(pe.PythonTraceback), inner); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
Tests/Common/Exceptions/ClrBubbledExceptionInterpreterTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. | ||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
using NUnit.Framework; | ||
using NUnit.Framework.Constraints; | ||
using Python.Runtime; | ||
using QuantConnect.Exceptions; | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace QuantConnect.Tests.Common.Exceptions | ||
{ | ||
[TestFixture] | ||
public class ClrBubbledExceptionInterpreterTests | ||
{ | ||
private string _pythonModuleName = "Test_PythonExceptionInterpreter"; | ||
private ClrBubbledException _dotnetException; | ||
private PythonException _pythonException; | ||
|
||
[OneTimeSetUp] | ||
public void Setup() | ||
{ | ||
using (Py.GIL()) | ||
{ | ||
var module = Py.Import(_pythonModuleName); | ||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke(); | ||
|
||
try | ||
{ | ||
// self.MarketOrder(null, 1) | ||
algorithm.dotnet_error(); | ||
} | ||
catch (ClrBubbledException e) | ||
{ | ||
_dotnetException = e; | ||
} | ||
|
||
try | ||
{ | ||
// x = 1 / 0 | ||
algorithm.zero_division_error(); | ||
} | ||
catch (PythonException e) | ||
{ | ||
_pythonException = e; | ||
} | ||
|
||
Assert.IsNotNull(_dotnetException); | ||
Assert.IsNotNull(_pythonException); | ||
} | ||
} | ||
|
||
[Test] | ||
[TestCase(typeof(Exception), ExpectedResult = false)] | ||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)] | ||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)] | ||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)] | ||
[TestCase(typeof(PythonException), ExpectedResult = false)] | ||
[TestCase(typeof(ClrBubbledException), ExpectedResult = true)] | ||
public bool CanInterpretReturnsTrueOnlyForClrBubbledExceptionType(Type exceptionType) | ||
{ | ||
var exception = CreateExceptionFromType(exceptionType); | ||
return new ClrBubbledExceptionInterpreter().CanInterpret(exception); | ||
} | ||
|
||
[Test] | ||
[TestCase(typeof(Exception), true)] | ||
[TestCase(typeof(KeyNotFoundException), true)] | ||
[TestCase(typeof(DivideByZeroException), true)] | ||
[TestCase(typeof(InvalidOperationException), true)] | ||
[TestCase(typeof(PythonException), true)] | ||
[TestCase(typeof(ClrBubbledException), false)] | ||
public void InterpretThrowsForNonClrBubbledExceptionTypes(Type exceptionType, bool expectThrow) | ||
{ | ||
var exception = CreateExceptionFromType(exceptionType); | ||
var interpreter = new ClrBubbledExceptionInterpreter(); | ||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing; | ||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint); | ||
} | ||
|
||
[Test] | ||
public void VerifyMessageContainsStackTraceInformation() | ||
{ | ||
var exception = CreateExceptionFromType(typeof(ClrBubbledException)); | ||
var assembly = typeof(ClrBubbledExceptionInterpreter).Assembly; | ||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies(new[] { assembly }); | ||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance); | ||
|
||
Assert.True(exception.Message.Contains("Value cannot be null. (Parameter 'key')", StringComparison.InvariantCulture)); | ||
Assert.True(exception.Message.Contains("at dotnet_error", StringComparison.InvariantCulture)); | ||
Assert.True(exception.Message.Contains("self.MarketOrder(None", StringComparison.InvariantCulture)); | ||
Assert.True(exception.Message.Contains($"in {_pythonModuleName}.py: line ", StringComparison.InvariantCulture)); | ||
} | ||
|
||
private Exception CreateExceptionFromType(Type type) | ||
{ | ||
if (type == typeof(ClrBubbledException)) | ||
{ | ||
return _dotnetException; | ||
} | ||
|
||
return type == typeof(PythonException) ? _pythonException : (Exception)Activator.CreateInstance(type); | ||
} | ||
} | ||
} |
Oops, something went wrong.