chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:02:50 +08:00
commit 0fc60fdcb1
5008 changed files with 910633 additions and 0 deletions
@@ -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);
}
}
}
@@ -0,0 +1,66 @@
/*
* 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;
namespace QuantConnect.Exceptions
{
/// <summary>
/// Interprets <see cref="DllNotFoundPythonExceptionInterpreter"/> instances
/// </summary>
public class DllNotFoundPythonExceptionInterpreter : IExceptionInterpreter
{
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public int Order => 0;
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </summary>
/// <param name="exception">The exception to check</param>
/// <returns>True if the exception can be interpreted, false otherwise</returns>
public bool CanInterpret(Exception exception)
{
return
exception?.GetType() == typeof(DllNotFoundException) &&
exception.Message.Contains("python");
}
/// <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 Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter)
{
var dnfe = (DllNotFoundException)exception;
var startIndex = dnfe.Message.IndexOfInvariant("python");
var length = Math.Min(dnfe.Message.Length - startIndex, 10);
var dllName = dnfe.Message.Substring(startIndex, length);
length = dllName.IndexOfInvariant('\'');
if (length > 0)
{
dllName = dllName.Substring(0, length);
}
var platform = Environment.OSVersion.Platform.ToString();
var message = Messages.DllNotFoundPythonExceptionInterpreter.DynamicLinkLibraryNotFound(dllName, platform);
return new DllNotFoundException(message, dnfe);
}
}
}
@@ -0,0 +1,49 @@
/*
* 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 QuantConnect.Interfaces;
namespace QuantConnect.Exceptions
{
/// <summary>
/// Defines an exception interpreter. Interpretations are invoked on <see cref="IAlgorithm.RunTimeError"/>
/// </summary>
public interface IExceptionInterpreter
{
/// <summary>
/// Determines the order that a class that implements this interface should be called
/// </summary>
int Order { get; }
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </summary>
/// <param name="exception">The exception to check</param>
/// <returns>True if the exception can be interpreted, false otherwise</returns>
bool CanInterpret(Exception exception);
/// <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.
/// This provides a link back allowing the inner exceptions to be interpreted using the interpreters
/// configured in the <see cref="IExceptionInterpreter"/>. Individual implementations *may* ignore
/// this value if required.</param>
/// <returns>The interpreted exception</returns>
Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter);
}
}
@@ -0,0 +1,55 @@
/*
* 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;
namespace QuantConnect.Exceptions
{
/// <summary>
/// Interprets <see cref="InvalidTokenPythonExceptionInterpreter"/> instances
/// </summary>
public class InvalidTokenPythonExceptionInterpreter : PythonExceptionInterpreter
{
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public override int Order => 0;
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </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)
{
return base.CanInterpret(exception) &&
(exception.Message.Contains(Messages.InvalidTokenPythonExceptionInterpreter.InvalidTokenExpectedSubstring, StringComparison.InvariantCultureIgnoreCase)
|| exception.Message.Contains(Messages.InvalidTokenPythonExceptionInterpreter.NotPermittedExpectedSubstring, StringComparison.InvariantCultureIgnoreCase));
}
/// <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 = (PythonException)exception;
return new Exception(Messages.InvalidTokenPythonExceptionInterpreter.InterpretException(pe), pe);
}
}
}
@@ -0,0 +1,78 @@
/*
* 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;
using System.Collections.Generic;
namespace QuantConnect.Exceptions
{
/// <summary>
/// Interprets <see cref="KeyErrorPythonExceptionInterpreter"/> instances
/// </summary>
public class KeyErrorPythonExceptionInterpreter : PythonExceptionInterpreter
{
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public override int Order => 0;
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </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)
{
var pythonException = exception as PythonException;
if (pythonException == null)
{
return false;
}
using (Py.GIL())
{
return base.CanInterpret(exception) &&
pythonException.Type.Name.Contains("KeyError", StringComparison.InvariantCultureIgnoreCase);
}
}
/// <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 = (PythonException)exception;
var key = string.Empty;
if (pe.Message.Contains('[', StringComparison.InvariantCulture))
{
key = pe.Message.GetStringBetweenChars('[', ']');
}
else if (pe.Message.Contains('\'', StringComparison.InvariantCulture))
{
key = pe.Message.GetStringBetweenChars('\'', '\'');
}
var message = Messages.KeyErrorPythonExceptionInterpreter.KeyNotFoundInCollection(key);
message += PythonUtil.PythonExceptionStackParser(pe.StackTrace);
return new KeyNotFoundException(message, pe);
}
}
}
@@ -0,0 +1,107 @@
/*
* 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="NoMethodMatchPythonExceptionInterpreter"/> instances
/// </summary>
public class NoMethodMatchPythonExceptionInterpreter : PythonExceptionInterpreter
{
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public override int Order => 0;
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </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)
{
return base.CanInterpret(exception) &&
exception.Message.Contains(Messages.NoMethodMatchPythonExceptionInterpreter.NoMethodMatchExpectedSubstring);
}
/// <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 = (PythonException)exception;
var methodName = GetMethodName(pe.Message);
var message = Messages.NoMethodMatchPythonExceptionInterpreter.AttemptedToAccessMethodThatDoesNotExist(methodName);
var overloadsHint = GetOverloadsHint(pe.Message);
if (!string.IsNullOrEmpty(overloadsHint))
{
message += $" {overloadsHint}";
}
message += PythonUtil.PythonExceptionStackParser(pe.StackTrace);
return new MissingMethodException(message, pe);
}
/// <summary>
/// Extracts the name of the method that failed to resolve from the Python exception message.
/// The message has the form: "No method matches given arguments for {methodName}: ({argumentTypes})",
/// so the method name sits between the "for " keyword and the following ":".
/// </summary>
private static string GetMethodName(string exceptionMessage)
{
const string forKeyword = "for ";
var forIndex = exceptionMessage.IndexOfInvariant(forKeyword);
if (forIndex == -1)
{
// Unexpected format, fall back to the whole message
return exceptionMessage.Trim();
}
var methodNameStart = forIndex + forKeyword.Length;
var colonIndex = exceptionMessage.IndexOf(':', methodNameStart);
var methodName = colonIndex > methodNameStart
? exceptionMessage.Substring(methodNameStart, colonIndex - methodNameStart)
: exceptionMessage.Substring(methodNameStart);
return methodName.Trim();
}
/// <summary>
/// Extracts the candidate-signatures hint pythonnet appends to the binding-failure
/// message ("The expected signature is:" or "The following overloads are available:"
/// followed by the signatures), so the interpreted message can keep it.
/// </summary>
private static string GetOverloadsHint(string exceptionMessage)
{
var hintIndex = exceptionMessage.IndexOfInvariant("The expected signature is:");
if (hintIndex == -1)
{
hintIndex = exceptionMessage.IndexOfInvariant("The following overloads are available:");
}
return hintIndex == -1 ? null : exceptionMessage.Substring(hintIndex).Trim();
}
}
}
@@ -0,0 +1,52 @@
/*
* 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="PythonExceptionInterpreter"/> instances
/// </summary>
public class PythonExceptionInterpreter : IExceptionInterpreter
{
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public virtual 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 virtual bool CanInterpret(Exception exception) => exception?.GetType() == typeof(PythonException);
/// <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 virtual Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter)
{
var pe = (PythonException)exception;
return new Exception(PythonUtil.PythonExceptionParser(pe), pe);
}
}
}
@@ -0,0 +1,63 @@
/*
* 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 QuantConnect.Scheduling;
namespace QuantConnect.Exceptions
{
/// <summary>
/// Interprets <see cref="ScheduledEventException"/> instances
/// </summary>
public class ScheduledEventExceptionInterpreter : IExceptionInterpreter
{
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public int Order => 0;
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </summary>
/// <param name="exception">The exception to check</param>
/// <returns>True if the exception can be interpreted, false otherwise</returns>
public bool CanInterpret(Exception exception) => exception?.GetType() == typeof(ScheduledEventException);
/// <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.
/// This provides a link back allowing the inner exceptions to be interpreted using the interpreters
/// configured in the <see cref="IExceptionInterpreter"/>. Individual implementations *may* ignore
/// this value if required.</param>
/// <returns>The interpreted exception</returns>
public Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter)
{
var see = (ScheduledEventException) exception;
var inner = innerInterpreter.Interpret(see.InnerException, innerInterpreter);
// prepend the scheduled event name
var message = exception.Message;
if (!message.Contains(see.ScheduledEventName))
{
message = Messages.ScheduledEventExceptionInterpreter.ScheduledEventName(see.ScheduledEventName);
}
return new ScheduledEventException(see.ScheduledEventName, message, inner);
}
}
}
@@ -0,0 +1,148 @@
/*
* 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 System.Linq;
using QuantConnect.Util;
using System.Reflection;
using QuantConnect.Logging;
using System.Collections.Generic;
namespace QuantConnect.Exceptions
{
/// <summary>
/// Interprets exceptions using the configured interpretations
/// </summary>
public class StackExceptionInterpreter : IExceptionInterpreter
{
private readonly List<IExceptionInterpreter> _interpreters;
/// <summary>
/// Stack interpreter instance
/// </summary>
public static readonly Lazy<StackExceptionInterpreter> Instance = new Lazy<StackExceptionInterpreter>(
() => StackExceptionInterpreter.CreateFromAssemblies());
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public int Order => 0;
/// <summary>
/// Initializes a new instance of the <see cref="StackExceptionInterpreter"/> class
/// </summary>
/// <param name="interpreters">The interpreters to use</param>
public StackExceptionInterpreter(IEnumerable<IExceptionInterpreter> interpreters)
{
_interpreters = interpreters.OrderBy(x => x.Order).ToList();
}
/// <summary>
/// Gets the interpreters loaded into this instance
/// </summary>
public IEnumerable<IExceptionInterpreter> Interpreters => _interpreters;
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </summary>
/// <param name="exception">The exception to check</param>
/// <returns>True if the exception can be interpreted, false otherwise</returns>
public bool CanInterpret(Exception exception)
{
return _interpreters.Any(interpreter => interpreter.CanInterpret(exception));
}
/// <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.
/// This provides a link back allowing the inner exceptions to be interpreted using the intepretators
/// configured in the <see cref="StackExceptionInterpreter"/>. Individual implementations *may* ignore
/// this value if required.</param>
/// <returns>The interpreted exception</returns>
public Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter = null)
{
if (exception == null)
{
return null;
}
foreach (var interpreter in _interpreters)
{
try
{
if (interpreter.CanInterpret(exception))
{
// use this instance to interpret inner exceptions as well, unless one was specified
return interpreter.Interpret(exception, innerInterpreter ?? this);
}
}
catch (Exception err)
{
Log.Error(err);
}
}
return exception;
}
/// <summary>
/// Combines the exception messages from this exception and all inner exceptions.
/// </summary>
/// <param name="exception">The exception to create a collated message from</param>
/// <returns>The collate exception message</returns>
public string GetExceptionMessageHeader(Exception exception)
{
return string.Join(" ", InnersAndSelf(exception).Select(e => e.Message));
}
/// <summary>
/// Creates a new <see cref="StackExceptionInterpreter"/> by loading implementations with default constructors from the specified assemblies
/// </summary>
/// <returns>A new <see cref="StackExceptionInterpreter"/> containing interpreters from the specified assemblies</returns>
public static StackExceptionInterpreter CreateFromAssemblies()
{
var interpreters =
// type implements IExceptionInterpreter
from type in Composer.Instance.GetExportedTypes<IExceptionInterpreter>()
// ignore non-public and non-instantiable abstract types
// type has default parameterless ctor
where type.IsPublic && !type.IsAbstract && type.GetConstructor([]) != null
// provide guarantee of deterministic ordering
orderby type.FullName
select (IExceptionInterpreter) Activator.CreateInstance(type);
var stackExceptionInterpreter = new StackExceptionInterpreter(interpreters);
foreach (var interpreter in stackExceptionInterpreter.Interpreters)
{
Log.Debug(Messages.StackExceptionInterpreter.LoadedExceptionInterpreter(interpreter));
}
return stackExceptionInterpreter;
}
private IEnumerable<Exception> InnersAndSelf(Exception exception)
{
yield return exception;
while (exception.InnerException != null)
{
exception = exception.InnerException;
yield return exception;
}
}
}
}
@@ -0,0 +1,93 @@
/*
* 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 System.Text.RegularExpressions;
namespace QuantConnect.Exceptions
{
/// <summary>
/// Base handler that will try get an exception file and line
/// </summary>
public class SystemExceptionInterpreter : IExceptionInterpreter
{
private static Regex FileAndLineRegex = new ("(\\w+.cs:line \\d+)", RegexOptions.Compiled);
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public virtual int Order => int.MaxValue;
/// <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 virtual bool CanInterpret(Exception exception) => true;
/// <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 virtual Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter)
{
var sanitized = new SanitizedException(exception.Message, exception.StackTrace);
if (!TryGetLineAndFile(exception.StackTrace, out var fileAndLine))
{
return sanitized;
}
return new Exception(exception.Message + fileAndLine, innerException: sanitized);
}
/// <summary>
/// Helper method to get the file and line from a C# stacktrace
/// </summary>
public static bool TryGetLineAndFile(string stackTrace, out string fileAndLine)
{
fileAndLine = null;
if (stackTrace != null)
{
var match = FileAndLineRegex.Match(stackTrace);
if (match.Success)
{
foreach (Match lineCapture in match.Captures)
{
fileAndLine = $" in {lineCapture.Groups[1].Value}" ;
return true;
}
}
}
return false;
}
private class SanitizedException : Exception
{
private readonly string _message;
private readonly string _stackTrace;
public override string Message => _message;
public override string StackTrace => _stackTrace;
public SanitizedException(string message, string stackTrace)
{
_message = message;
_stackTrace = Logging.Log.ClearLeanPaths(stackTrace);
}
}
}
}
@@ -0,0 +1,60 @@
/*
* 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="UnsupportedOperandPythonExceptionInterpreter"/> instances
/// </summary>
public class UnsupportedOperandPythonExceptionInterpreter : PythonExceptionInterpreter
{
/// <summary>
/// Determines the order that an instance of this class should be called
/// </summary>
public override int Order => 0;
/// <summary>
/// Determines if this interpreter should be applied to the specified exception.
/// </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)
{
return base.CanInterpret(exception) &&
exception.Message.Contains(Messages.UnsupportedOperandPythonExceptionInterpreter.UnsupportedOperandTypeExpectedSubstring);
}
/// <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 = (PythonException)exception;
var types = pe.Message.Split(':')[1].Trim();
var message = Messages.UnsupportedOperandPythonExceptionInterpreter.InvalidObjectTypesForOperation(types);
message += PythonUtil.PythonExceptionStackParser(pe.StackTrace);
return new Exception(message, pe);
}
}
}