Skip to content

Name the unexpected keyword argument in the bind-failure TypeError - #144

Merged
jhonabreul merged 5 commits into
QuantConnect:masterfrom
jhonabreul:feature-unexpected-keyword-argument-error
Aug 12, 2026
Merged

Name the unexpected keyword argument in the bind-failure TypeError#144
jhonabreul merged 5 commits into
QuantConnect:masterfrom
jhonabreul:feature-unexpected-keyword-argument-error

Conversation

@jhonabreul

@jhonabreul jhonabreul commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

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:

market_order(symbol, -10, as_tag="EmergencyFlatten")
TypeError: No method matches given arguments for market_order: (<class 'QuantConnect.Symbol'>, <class 'int'>). The following overloads are available: ...

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.AppendUnexpectedKeywordArgument runs while the bind-failure message is built: when a supplied kwarg name is accepted by no candidate overload (same candidate set Bind used, 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:

    TypeError: No method matches given arguments for market_order: (<class 'QuantConnect.Symbol'>, <class 'int'>). Got an unexpected keyword argument 'as_tag'. Did you mean 'tag'? The following overloads are available: ...
    
  • The Did you mean hint 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_call slot, where an escaping exception would propagate into CPython and mask the bind failure; on error the TypeError is raised with whatever was appended so far.

A complete message as produced against the new test fixture:

TypeError: No method matches given arguments for order_like_method: (<class 'str'>, <class 'int'>). Got an unexpected keyword argument 'as_tag'. Did you mean 'tag'? The expected signature is:
  order_like_method(symbol: str, quantity: float, asynchronous: bool = False, tag: str = "", order_properties: Any = None)

Note: the message keeps the No method matches given arguments for {name}: prefix, so Lean's NoMethodMatchPythonExceptionInterpreter keeps matching and rewriting it exactly as before; the kwarg detail rides along inside it.

Note on #147: ClassBase's private LevenshteinDistance moved verbatim to Util.LevenshteinDistance, used by both ClassBase and MethodBinder. #147 deletes the ClassBase call site in favor of Jaro-Winkler; the shared helper remains for MethodBinder, 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, and Did you mean 'tag'? is suggested.
  • test_unexpected_keyword_argument_without_suggestion: unrelated kwarg name; asserts no Did you mean hint.
  • 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.
  • Full python suite (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.
  • Full embed suite (dotnet test src/embed_tests -c Release): 971 passed, 0 failed, 8 skipped.

Checklist

Check all those that are applicable and complete.

  • Make sure to include one or more tests for your change
  • If an enhancement PR, please create docs and at best an example
  • Ensure you have signed the .NET Foundation CLA
  • Add yourself to AUTHORS
  • Updated the CHANGELOG

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.
@jhonabreul jhonabreul changed the title Raise a proper unexpected-keyword-argument TypeError on bind failure Name the unexpected keyword argument in the bind-failure TypeError Aug 11, 2026
@jhonabreul
jhonabreul merged commit 3464917 into QuantConnect:master Aug 12, 2026
9 checks passed
@jhonabreul
jhonabreul deleted the feature-unexpected-keyword-argument-error branch August 12, 2026 20:33
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants