Skip to content

Converting Callable Python to Dotnet Delegate#2015

Closed
eirannejad wants to merge 5 commits into
pythonnet:masterfrom
mcneel:pr/delegateParams
Closed

Converting Callable Python to Dotnet Delegate#2015
eirannejad wants to merge 5 commits into
pythonnet:masterfrom
mcneel:pr/delegateParams

Conversation

@eirannejad
Copy link
Copy Markdown
Contributor

@eirannejad eirannejad commented Nov 17, 2022

What does this implement/fix? Explain your changes.

When a dotnet method requries a delegate as a parameter, pythonnet fails to convert a python function into a dotnet delegate

  public delegate void DelegateHandler(int first, float second);

  public static class DelegateParameterTest
  {
    public static void DoSomething(DelegateHandler handler) => handler(1, 2);
  }

⚠️ This will fail:

from PyNetTests import DelegateParameterTest

def Handler(first, second):
	print(first, second)

DelegateParameterTest.DoSomething(Handler)

Does this close any currently open issues?

Not that I know of

Any other comments?

No

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

@eirannejad eirannejad marked this pull request as draft November 17, 2022 20:45
@eirannejad
Copy link
Copy Markdown
Contributor Author

Hello friends. I'd love to get a review on this to improve and fix. I'll then create the necessary tests and will mark this as final

@eirannejad eirannejad changed the title First draft of Converting Callable Python to Dotnet Delegate Converting Callable Python to Dotnet Delegate Nov 17, 2022
@eirannejad
Copy link
Copy Markdown
Contributor Author

Self notes:

@eirannejad
Copy link
Copy Markdown
Contributor Author

eirannejad commented Nov 17, 2022

@filmor Sorry to tag you directly here but all tests are failing on this one commit I added to the master branch. They are related to this analyzer

CSC : warning AD0001: Analyzer 'NonCopyable.NonCopyableAnalyzer' threw an exception of type
'System.InvalidCastException' with message 'Unable to cast object of type
'Microsoft.CodeAnalysis.Operations.ArrayInitializerOperation' to type
'Microsoft.CodeAnalysis.Operations.IArrayCreationOperation'.'. [/home/ubuntu/actions-runner/_work/pythonnet/pythonnet/src/testing/Python.Test.csproj]

Not sure where the problem is

@lostmsu
Copy link
Copy Markdown
Member

lostmsu commented Nov 29, 2022

@eirannejad

... all tests are failing ... They are related to
CSC : warning AD0001

No they are not. That message is just a warning.

@eirannejad eirannejad marked this pull request as ready for review December 2, 2022 16:57
@filmor
Copy link
Copy Markdown
Member

filmor commented Jan 24, 2023

Looks good to me. @lostmsu?

{
if (Runtime.PyTuple_Size(args) != 1)
{
throw new Exception("Event handler methods only accept one Delegate argument");
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.

This must be generating TypeError

Comment thread src/runtime/Converter.cs
throw new ArgumentException("We should never receive instances of other managed types");
}

// NOTE: generate a delegate to cast a python callable into a System.Delegate
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.

This should either be part of ToPrimitive, or at very least moved down so that codecs could override this behavior.

Also @filmor even if this is corrected this is a breaking change as it might fail or change overload resolution.

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.

Can you give an example that worked before and doesn't with this merged? I don't get how this would change the overload resolution in a breaking fashion.

Copy link
Copy Markdown
Member

@lostmsu lostmsu Jan 25, 2023

Choose a reason for hiding this comment

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

void Foo(PyObject x) vs void Foo(System.Action x) previously would unambiguously resolve to the first variant. With this change it will either fail due to non-unique resolution or attempt to prioritize, which might or might not result in the second one being selected.

We previously made similar and even more drastic changes in 2.x branch. Question is do we want to continue in 3.x?

This could be put into a decoder.

It is actually a questionable default, considering what stuff can turn out to be callable in popular Python libraries.

@eirannejad eirannejad closed this Dec 20, 2023
@eirannejad eirannejad deleted the pr/delegateParams branch December 20, 2023 22:13
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.

3 participants