Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method overload object type #377

Merged
merged 3 commits into from
Feb 22, 2017
Merged

Conversation

vmuriart
Copy link
Contributor

What does this implement/fix? Explain your changes.

Fixes Method object overloading without breaking changes introduced by #131 and #151.

I added the tests/examples from #131 to the tests to ensure that the behavior didn't get reverted.

Does this close any currently open issues?

Closes #203

Any other comments?

This patch fixes the issue from #203, but MethodBinder.Bind needs rewriting since its basically been patched over and over again to fix edge cases. I didn't want to do it as part of this pull_request since it would affect more than just fixing #203.

Checklist

Check all those that are applicable and complete.

  • Make sure to include one or more tests for your change
  • Add yourself to AUTHORS

@den-run-ai
Copy link
Contributor

@vmuriart what happens with multiple arguments, when overloaded methods have object argument?

@vmuriart
Copy link
Contributor Author

@denfromufa good question. No idea.

foo(int a, object b)
foo(object a, int b)
foo(object a, object b)
foo(int a, int b)

These 4 functions look enough to cover the possibilities or do I need more?

@den-run-ai
Copy link
Contributor

we need one super-loaded method which covers all these cases from this meta-issue :)

#265

@vmuriart
Copy link
Contributor Author

That sounds much broader than the scope of this pull_request.
I'm planning on refactoring methodbinder to clean up alot of what is going in there.

@den-run-ai
Copy link
Contributor

@vmuriart I understand, your example looks good. My suggestion was not serious anyway. But we may hit issues when dealing with sub-classes and ambiguous cases in the overload. IMO, pythonnet should be very strict by default in method resolution. See examples how C# compiler had to break method overloading in .NET 4.0:

http://csharpindepth.com/Articles/General/Overloading.aspx

@vmuriart
Copy link
Contributor Author

@denfromufa No worries. My goal is to restore similar behavior to what pythonnet==2.0.0 had irt method objects. I had to freeze the version of pythonnet I was using to v2.0 because of it.
I'm ok w switching to a stricter method resolution, as long as it is part of v3.0 😄

@vmuriart
Copy link
Contributor Author

@denfromufa Multiple arguments with objects works as expected.

@den-run-ai
Copy link
Contributor

den-run-ai commented Feb 15, 2017

@vmuriart no failure cases in overloads to make sure that they fail. No strings in overloaded method arguments when creating the methods in c#, but then you use strings as arguments when invoking from python.

@vmuriart vmuriart force-pushed the method_object branch 3 times, most recently from 17499ae to c9ab4ea Compare February 15, 2017 07:24
@vmuriart
Copy link
Contributor Author

I think I understood your request correctly. I added a test to check for failure/exception.

@den-run-ai
Copy link
Contributor

den-run-ai commented Feb 15, 2017 via email

@vmuriart
Copy link
Contributor Author

@denfromufa I think you are asking for these tests I added them on a separate commit.

Earlier when I was working on this pull request I used those tests to make sure I wasn't reverting the behavior you are describing. On earlier implementations, I reverted the behavior so those tests kept me in check.

The string-string check is analogous to the int-int check vs obj-obj check

@den-run-ai
Copy link
Contributor

@vmuriart string check is not analogous, you are assuming that strings are object in your tests. In fact string is subclass of object.

@vmuriart
Copy link
Contributor Author

vmuriart commented Feb 15, 2017

@denfromufa int are also a subclass of System.Object.

System.Object
   System.ValueType
      System.Int32

Sources:

@den-run-ai
Copy link
Contributor

yes, int is also object subclass. However you use int in C# overloaded methods, while not using strings. Let me give some examples.

@den-run-ai
Copy link
Contributor

den-run-ai commented Feb 16, 2017

@vmuriart here is what I suggested to add. I cannot test locally, due to #385

public static string TestOverloadedObject(object o)
        {
            return "Got object";
        }

        public static string TestOverloadedObjectTwo(int a, int b)
        {
            return "Got int-int";
        }

        public static string TestOverloadedObjectTwo(string a, string b)
        {
            return "Got string-string";
        }

        public static string TestOverloadedObjectTwo(string a, int b)
        {
            return "Got string-int";
        }

        public static string TestOverloadedObjectTwo(string a, object b)
        {
            return "Got string-object";
        }

        public static string TestOverloadedObjectTwo(int a, object b)
        {
            return "Got int-object";
        }

        public static string TestOverloadedObjectTwo(object a, int b)
        {
            return "Got object-int";
        }

        public static string TestOverloadedObjectTwo(object a, object b)
        {
            return "Got object-object";
        }

        public static string TestOverloadedObjectThree(object a, int b)
        {
            return "Got object-int";
        }

        public static string TestOverloadedObjectThree(int a, object b)
        {
            return "Got int-object";
        }
def test_object_in_multiparam():
    """Test method with object multiparams behaves"""

    res = MethodTest.TestOverloadedObjectTwo(5, 5)
    assert res == "Got int-int"

    res = MethodTest.TestOverloadedObjectTwo(5, "foo")
    assert res == "Got int-object"

    res = MethodTest.TestOverloadedObjectTwo("foo", 5)
    assert res == "Got object-int"

    res = MethodTest.TestOverloadedObjectTwo("foo", "bar")
    assert res == "Got object-object"

    res = MethodTest.TestOverloadedObjectTwo("foo", System.Object)
    assert res == "Got string-object"
   
    res = MethodTest.TestOverloadedObjectTwo("foo", "bar")
    assert res == "Got string-string"

    res = MethodTest.TestOverloadedObjectTwo("foo", 5)
    assert res == "Got string-int"

@vmuriart
Copy link
Contributor Author

@denfromufa Added your tests, but had to modify remove a couple of the conditions I had added earlier since the function signatures had changed.

@@ -375,7 +375,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
if (clrtype != null)
{
var typematch = false;
if (pi[n].ParameterType != clrtype)
if (pi[n].ParameterType != typeof(object) && pi[n].ParameterType != clrtype)
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add brackets around each logical?

@den-run-ai
Copy link
Contributor

@vmuriart I left 2 comments inline with the code

@vmuriart
Copy link
Contributor Author

vmuriart commented Feb 18, 2017 via email

@den-run-ai
Copy link
Contributor

den-run-ai commented Feb 18, 2017 via email

@vmuriart
Copy link
Contributor Author

@denfromufa Added the parenthesis. Good to squash-merge?

@den-run-ai
Copy link
Contributor

you did not address the second comment. @vmuriart will this break if you add:

public static string TestOverloadedObjectTwo(int a, string b)
        {
            return "Got int-string";
        }

@vmuriart
Copy link
Contributor Author

There was only a single comment.

image

And the answer is no. It simply changes the result of which method is used as it will pick the closest match it can find before it picked object.

@den-run-ai
Copy link
Contributor

so can you add it? because testing closest match is important.

so you don't see this?

image

@vmuriart
Copy link
Contributor Author

It's not there. It even says on your screen shot that its pending.

Copy link
Contributor

@den-run-ai den-run-ai left a comment

Choose a reason for hiding this comment

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

testing

res = MethodTest.TestOverloadedObjectTwo(5, 5)
assert res == "Got int-int"

res = MethodTest.TestOverloadedObjectTwo(5, "foo")
Copy link
Contributor

Choose a reason for hiding this comment

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

will this break if you add:

public static string TestOverloadedObjectTwo(int a, string b)
        {
            return "Got int-string";
        }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now its there.

@codecov
Copy link

codecov bot commented Feb 20, 2017

Codecov Report

Merging #377 into master will increase coverage by 0.07%.
The diff coverage is 100%.

@@            Coverage Diff             @@
##           master     #377      +/-   ##
==========================================
+ Coverage   63.27%   63.35%   +0.07%     
==========================================
  Files          61       61              
  Lines        5226     5226              
  Branches      860      860              
==========================================
+ Hits         3307     3311       +4     
+ Misses       1697     1695       -2     
+ Partials      222      220       -2
Flag Coverage Δ
#Embedded_Tests 32.57% <100%> (-0.02%)
#Python_Tests 60.64% <100%> (+0.07%)
#Setup_Linux 74% <100%> (ø)
#Setup_Windows 70.5% <100%> (ø)
Impacted Files Coverage Δ
src/runtime/methodbinder.cs 90.61% <100%> (ø)
src/runtime/converter.cs 77.89% <ø> (+1.05%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e753b72...0ae9c38. Read the comment docs.

@vmuriart
Copy link
Contributor Author

Added test and its passing as well.

return "Got object-int";
}

public static string TestOverloadedObjectTwo(object a, object b)
Copy link
Contributor

@den-run-ai den-run-ai Feb 21, 2017

Choose a reason for hiding this comment

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

you don't test this method in python

Copy link
Contributor Author

Choose a reason for hiding this comment

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

because you changed the test for it above. I re-added a test for it.

@vmuriart
Copy link
Contributor Author

@denfromufa test added and passing as well.

@den-run-ai
Copy link
Contributor

@vmuriart I'm still surprised that this does not break ;) i approve on my side. in the future we should definitely improve testing all these combinations of arguments by using hypothesis or parametrizing pytest. Let's release v2.3.0.dev1 version after this merge.

@filmor @tonyroberts please review!

@vmuriart
Copy link
Contributor Author

@denfromufa I didn't want to introduce parametrizing tests yet. I figured I'd slowly introduce py.test features instead of all at once.

@vmuriart vmuriart force-pushed the method_object branch 3 times, most recently from db6c2ac to 0ae9c38 Compare February 21, 2017 19:45
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.

Pythonnet 2.1 not identifying System.Object type
3 participants