Name the unexpected keyword argument in the bind-failure TypeError - #144
Merged
jhonabreul merged 5 commits intoAug 12, 2026
Merged
Conversation
When a method call fails to bind and one of the supplied keyword arguments
matches no parameter of any candidate overload, the generic 'No method
matches given arguments' message did not mention the keyword argument at
all (only positional argument types are echoed), leaving the actual
mistake invisible, e.g.:
market_order(symbol, -10, as_tag="EmergencyFlatten")
-> No method matches given arguments for market_order:
(<class 'Symbol'>, <class 'int'>). The following overloads ...
Now such calls raise the Python-style error instead, naming the offending
kwarg and suggesting the closest parameter name when one exists:
market_order() got an unexpected keyword argument 'as_tag'.
Did you mean 'tag'?
When every kwarg name is valid for some overload but binding still fails,
the existing no-method-matches message is preserved.
Moves ClassBase's private LevenshteinDistance implementation verbatim to Util.LevenshteinDistance and uses it from both call sites, removing the duplicate introduced for keyword-argument suggestions.
…d of replacing it
Martin-Molinero
approved these changes
Aug 12, 2026
jhonabreul
added a commit
to jhonabreul/pythonnet
that referenced
this pull request
Aug 12, 2026
Keeps the Jaro-Winkler scoring from this branch in ClassBase while retaining Util.LevenshteinDistance, which MethodBinder's unexpected-kwarg suggestion (QuantConnect#144) still uses. Also moves the DiagnoseClosestOverloadMismatch block inside the bind-failure try so master compiles again: QuantConnect#144 wrapped the message construction (including the candidates declaration) in try/catch after QuantConnect#145 had added the mismatch diagnosis below it, leaving 'candidates' out of scope at its use site.
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.
What does this implement/fix? Explain your changes.
When a call fails to bind because of a misspelled keyword argument, the error did not mention the kwarg at all — only positional argument types are echoed — so the actual mistake was invisible:
Cause:
MethodBinder.Invoke's bind-failure path builds its message from the positional args tuple only and has no unexpected-keyword-argument path.The fix:
MethodBinder.AppendUnexpectedKeywordArgumentruns while the bind-failure message is built: when a supplied kwarg name is accepted by no candidate overload (same candidate setBindused, so snake_case and original parameter names are matched exactly like binding does), it extends the existing message — right after the positional argument types, before the overload list — naming the first unknown kwarg in call order like CPython:The
Did you meanhint suggests the closest parameter name across all overloads (small local Levenshtein plus containment for 3+ character names); it is omitted when nothing is similar.When every kwarg name is valid for some overload but binding still fails (e.g. a type mismatch, or an argument supplied both positionally and by name), the message is unchanged.
The whole message-construction block (including the pre-existing name/argument-types/overloads parts) is now wrapped in a try/catch: it runs over arbitrary caller input inside the
tp_callslot, where an escaping exception would propagate into CPython and mask the bind failure; on error theTypeErroris raised with whatever was appended so far.A complete message as produced against the new test fixture:
Note: the message keeps the
No method matches given arguments for {name}:prefix, so Lean'sNoMethodMatchPythonExceptionInterpreterkeeps matching and rewriting it exactly as before; the kwarg detail rides along inside it.Note on #147:
ClassBase's privateLevenshteinDistancemoved verbatim toUtil.LevenshteinDistance, used by bothClassBaseandMethodBinder. #147 deletes theClassBasecall site in favor of Jaro-Winkler; the shared helper remains forMethodBinder, so the merge interplay is a trivial deletion on their side.Does this close any currently open issues?
No. Part of the error-surface improvements from QuantConnect/Agents#305 (improvement 1: fleet evidence A-70ad2e3b).
Any other comments?
Tests:
test_unexpected_keyword_argument_with_suggestion: unknown kwarg via both the snake_case and original PascalCase method names; asserts the no-match prefix is kept, the kwarg is named, andDid you mean 'tag'?is suggested.test_unexpected_keyword_argument_without_suggestion: unrelated kwarg name; asserts noDid you meanhint.test_unexpected_keyword_argument_reports_first_in_call_order: two unknown kwargs; asserts the first is reported.test_valid_keyword_arguments_still_bind: valid kwargs on the new fixture method bind and execute.test_valid_keyword_argument_names_keep_no_match_message: valid kwarg names with an unbindable call keep the classic no-method-matches message with no kwarg detail appended.py -3.11 -m pytest --runtime netcore tests): 461 passed, 23 skipped, 1 failed — the failure (test_explicit_assembly_load) is environmental and fails identically on unmodified master.dotnet test src/embed_tests -c Release): 971 passed, 0 failed, 8 skipped.Checklist
Check all those that are applicable and complete.
AUTHORSCHANGELOG