Accept integral floats for int params, hint overloads on bind failure (2.0.57)#128
Open
jhonabreul wants to merge 4 commits into
Open
Accept integral floats for int params, hint overloads on bind failure (2.0.57)#128jhonabreul wants to merge 4 commits into
jhonabreul wants to merge 4 commits into
Conversation
…gral Passing a Python float where a .NET integer parameter was expected behaved inconsistently: - Single-overload targets silently truncated any float (e.g. 5.5 -> 5) via Converter.ToManaged. - Overloaded targets rejected every float, including integral-valued ones (e.g. 5.0), with "No method matches given arguments" because the overload disambiguation path did not treat float->int as a valid conversion. This broke calls like RangeConsolidator(period) in Lean when period was a float. Make both paths consistent: an integral-valued float (5.0) is accepted and converted for integer parameters, while a non-integral float (5.5) is rejected with a TypeError instead of being silently truncated. - MethodBinder: treat integral Python floats as implicit-conversion candidates for integer parameters (enums excluded). - Converter.ToPrimitive: reject non-integral Python floats targeting integer types so truncation never happens silently. - Add a shared Type.IsInteger() helper in Util and use it in both places. - Add TestFloatToIntConversion covering single and overloaded ctor/method. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When argument binding fails, the raised TypeError only reported the argument
types that were passed, giving no clue what the method actually expected. For
example RangeConsolidator(5.5) produced:
No method matches given arguments for .ctor: (<class 'float'>)
Append the candidate overload signatures to the message so the caller can see
what was expected (e.g. that an int overload exists when a float was passed).
This applies to every "no match" case, not just numeric conversions.
- Single candidate -> ". The expected signature is:" + one signature.
- Multiple candidates -> ". The following overloads are available:" + list
(distinct, capped at 10 with "... and N more").
Signatures are rendered readably: friendly type names (by-ref/nullable
unwrapped, generics as Name[Arg1, Arg2]), params marked, optional parameters
shown with their default. The whole hint is best-effort and wrapped in a
try/catch so it can never mask the original binding failure.
- MethodBinder: add AppendOverloads/FormatSignature/FormatType/FormatDefaultValue
and emit the hint from Invoke's no-binding path.
- Add message tests to TestFloatToIntConversion (single and multiple overloads).
- Update TestCallbacks.TestNoOverloadException: the argument types are no longer
at the end of the message, so assert containment instead of suffix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "No method matches" hint now uses the snake_case names Python callers
actually use, both in the message header and in each candidate signature:
No method matches given arguments for compute_scaled: (<class 'float'>). The expected signature is:
compute_scaled(Int32 scale_factor)
- Add SnakeCaseName(MethodBase) and use it for the header and FormatSignature
(constructors keep their special .ctor token).
- Snake_case parameter names in FormatSignature via Name.ToSnakeCase().
- Add tests: method name and parameter names are snake_cased for single and
multiple overloads.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump AssemblyVersion/AssemblyFileVersion and the perf-test baseline reference to 2.0.57 to match the package <Version>. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
189ef5f to
e3640ac
Compare
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two related improvements to method/constructor argument binding, plus a version bump.
1. Accept integral-valued floats for integer parameters; reject non-integral ones.
Passing a Python
floatwhere a .NET integer parameter was expected behaved inconsistently:5.5→5) viaConverter.ToManaged.5.0), with "No method matches given arguments", because the overload-disambiguation path did not treatfloat→intas a valid conversion. This broke calls likeRangeConsolidator(period)in Lean whenperiodwas a float.Both paths are now consistent: an integral-valued float (
5.0) is accepted and converted for integer parameters, while a non-integral float (5.5) is rejected with aTypeErrorinstead of being silently truncated.MethodBinder: treat integral Python floats as implicit-conversion candidates for integer parameters (enums excluded).Converter.ToPrimitive: reject non-integral Python floats targeting integer types so truncation never happens silently.Type.IsInteger()helper inUtiland used it in both places.2. Hint the candidate overloads in the "No method matches"
TypeError.When binding failed, the error only reported the argument types that were passed, giving no clue what the method actually expected. The message now appends the candidate overload signature(s), using the snake_case names Python callers use (method names and parameter names; constructors keep the special
.ctortoken). This applies to every "no match" case, not just numeric conversions.Single candidate — a method taking a single
int, showing the snake_case method and parameter name:Multiple candidates — an overloaded method, each candidate listed in snake_case:
The
Int32parameter is now visible, hinting that an integer was expected. For Lean'sRangeConsolidator(5.5)the two constructor overloads are likewise listed with snake_case parameters (e.g.volume_selector). Signatures are rendered readably (friendly type names, by-ref/nullable unwrapped, generics asName[Arg1, Arg2],paramsmarked, optional parameters shown with their default). The list is de-duplicated and capped at 10 with a "... and N more" suffix. The whole hint is best-effort and wrapped in atry/catchso it can never mask the original binding failure.3. Version bump.
QuantConnect.pythonnet<Version>bumped2.0.56→2.0.57(with the matchingAssemblyVersion/AssemblyFileVersioninProperties/AssemblyInfo.cs).