Skip to content

Raise overload resolution exception in Python bindings if overload resolution fails#19312

Merged
opencv-pushbot merged 1 commit intoopencv:3.4from
VadimLevin:dev/vlevin/clear-msg-for-failed-overload-resolution
Jan 18, 2021
Merged

Raise overload resolution exception in Python bindings if overload resolution fails#19312
opencv-pushbot merged 1 commit intoopencv:3.4from
VadimLevin:dev/vlevin/clear-msg-for-failed-overload-resolution

Conversation

@VadimLevin
Copy link
Copy Markdown
Contributor

Python doesn't support function overloads, but OpenCV is C++ library and massively utilize them. If user has wrong input for overloaded function he/she receives only the latest conversion error message and sometimes it is not clear what is going on.

If every argument parsing function reports good diagnostic message why the argument can't be parsed, user will have sufficient information to fix the problem - overload resolution exception contains information about each conversion error.

Resolves #16432, #15465

Example error message output:

OpenCV(3.4.13-dev) :-1: error: (-5:Bad argument) in function 'testOverloadResolution'
> Overload resolution failed:
>  - Argument 'value' is required to be an integer
>  - function takes exactly 4 arguments (3 given)

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to switch conversions errors to C++ exceptions (instead of creation of Python exceptions)?

@VadimLevin
Copy link
Copy Markdown
Contributor Author

Does it make sense to switch conversions errors to C++ exceptions (instead of creation of Python exceptions)?

It is long term task, because we have to update all conversion functions to this logic and C++ exceptions have higher costs for this task - it looks like we need something that behaves in the same way as purposed std::expected - either the converted value or error - it should have the minimal impact on the function call cost.

@VadimLevin VadimLevin force-pushed the dev/vlevin/clear-msg-for-failed-overload-resolution branch from 2190d33 to 69b57eb Compare January 13, 2021 12:22
const std::size_t header_size = 27;
const std::string bullet = "\n - ";

// Estimate required buffer size - save dynamic memory allocations = faster
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raise

This code works in case of errors only, so it is not a part of code flow critical path (no need to optimize this aggressively).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but it is ~x8 times faster than std::ostringstream variant... 🤓

' conversionErrors.reserve({});\n'.format(len(all_code_variants))
code += ' \n'.join(gen_template_overloaded_function_call.substitute(variant=v)
for v in all_code_variants)
code += ' if (!conversionErrors.empty())\n' \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this condition be false? (conversionErrors.empty() is true)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In normal scenario: no - every overload resolution should succeed or fail setting an error, but there might be ill-formed pyopencv_to functions e.g. pyopencv_to_generic_vec - which has code path returning false, but without setting an error moreover there are some generated conversion (still need to be checked).
I think we can leave this check until stated problem is resolved (all conversions are tested - there not so many left, because we need to implement correct parsing objects those conform to sequence protocol e.g. tuples, lists, 1d numpy arrays or user classes (will be supported automatically)). What do you think?

@VadimLevin VadimLevin force-pushed the dev/vlevin/clear-msg-for-failed-overload-resolution branch 3 times, most recently from 2c0e7c1 to 1ab1c08 Compare January 14, 2021 13:40
{
const std::vector<std::string>& conversionErrors = conversionErrorsTLS.getRef();
const std::size_t conversionErrorsCount = conversionErrors.size();
if (conversionErrorsCount > 0) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps separate function can be extracted to be reused later + better readability:

string concatStrings(const list<string> & items, const string & prefix = string(), const string & item_prefix = srting());

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that we can leave this 1 time used code here, if it occurs that somebody want's to concatenate strings in this module too - definitely function should be extracted.

@VadimLevin VadimLevin force-pushed the dev/vlevin/clear-msg-for-failed-overload-resolution branch from 1ab1c08 to a0bdb78 Compare January 18, 2021 13:30
@opencv-pushbot opencv-pushbot merged commit 6ce9bb6 into opencv:3.4 Jan 18, 2021
@alalek alalek mentioned this pull request Jan 22, 2021
@alalek alalek mentioned this pull request Apr 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect error message for non-integer points in rectangle draw function: TypeError: function takes exactly 4 arguments (2 given)

4 participants