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

Add tests for conversions in Python method calls #10840

Merged
merged 1 commit into from
Jul 6, 2020

Conversation

mmisol
Copy link
Collaborator

@mmisol mmisol commented Jul 2, 2020

Purpose

Adds tests for the following conversion scenarios:

  • Python list => .NET IList (CPython fails)
  • .NET array => Python list
  • Python tuple => .NET array
  • Python tuple => .NET IList (CPython fails)
  • Python range => .NET array
  • Python range => .NET IList (CPython fails)
  • Python dict => .NET IDictionary (CPython fails)
  • .NET IDictionary => Python dict (CPython unkonwn)

Also commented out some tests that fail in both engines but may be
considered to fix in CPython:

  • .NET IList => Python list (call a Python list method on an IList?)
  • Python array => .NET IList (builtin library, may be uncommon)
  • Python dict => DS Dictionary (may deserve special attention)

Other types considered but not added as tests:

  • classes (can't convert them)
  • dictionary view objects (uncommon)
  • bytes, bytearray, memoryview (uncommon)
  • set, frozenset (uncommon)
  • complex (uncommon)

Other scenarios that might be interesting:

  • Mutability of collections (IronPython supports this for a IList)

Declarations

Check these if you believe they are true

  • The codebase is in a better state after this PR
  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • All tests pass using the self-service CI.
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning and are documented in the API Changes document.

Reviewers

@DynamoDS/dynamo

Adds tests for the following conversion scenarios:
- Python list => .NET IList (CPython fails)
- .NET array => Python list
- Python tuple => .NET array
- Python tuple => .NET IList (CPython fails)
- Python range => .NET array
- Python range => .NET IList (CPython fails)
- Python dict => .NET IDictionary (CPython fails)
- .NET IDictionary => Python dict (CPython unkonwn)

Also commented out some tests that fail in both engines but may be
considered to fix in CPython:
- .NET IList => Python list
- Python array => .NET IList
- Python dict => DS Dictionary

Other types considered but not added as tests:
- classes (can't convert them)
- dictionary view objects (uncommon)
- bytes, bytearray, memoryview (uncommon)
- set, frozenset (uncommon)
- complex (uncommon)
@mmisol mmisol requested a review from a team July 2, 2020 21:33
Copy link
Contributor

@QilongTang QilongTang left a comment

Choose a reason for hiding this comment

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

LGTM

@aparajit-pratap
Copy link
Contributor

Are these supported in IronPython:

  • Python tuple => .NET array
  • Python tuple => .NET IList (CPython fails)

@mmisol
Copy link
Collaborator Author

mmisol commented Jul 6, 2020

@aparajit-pratap Yes. Where I wrote CPython fails it should be interpreted as that and also IronPython works. Also, where I didn't write anything is for cases where they both work.

# Python tuple => .NET array - Works in both
a = DummyCollection.MakeArray(t)
# Python tuple => .NET IList - Does not work in CPython
l = List.AddItemToEnd(4, t)
Copy link
Contributor

Choose a reason for hiding this comment

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

Are Python tuples mutable?

r = range(0, 10, 2)
# Python range => .NET array - Works in both
a = DummyCollection.MakeArray(r)
# Python range => .NET IList - Does not work in CPython
Copy link
Contributor

Choose a reason for hiding this comment

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

Are Python ranges mutable? Do they result in lists or arrays? Please bear with the ignorant questions - I'm not a Python expert. Could there by differences in IronPython vs. CPython in the way that tuples, ranges, etc. behave in terms of mutability?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not problem at all. These are very good questions @aparajit-pratap .

Are Python ranges mutable?

What happens when a Python primitive gets passed to a .NET function call, is that the primitive gets converted to a .NET object. This means that in practice they are not mutable because what we get is not even in the Python world.

Do they result in lists or arrays?

This will depend on the declared type in the function call. Support for arrays was already built into Python.NET. For lists, a few minor changes were needed, but most of the logic can be reused.

Could there by differences in IronPython vs. CPython in the way that tuples, ranges, etc. behave in terms of mutability?

I don't think I have tested that. That's a very good point. I'll take a look at IronPython and see if I'm able to mutate a list for instance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I just checked and mutability can be achieved in IronPython for a List. You need to use a Zero Touch node to test it though, because List methods always make a copy.

from FFITarget import DummyCollection

d = {'one': 1, 'two': 2, 'three': 3}
# Python dict => DS Dictionary - Does not work in either engine
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if this is intended. It would be good to have but if it were to be supported, we would most likely need to make custom changes in pythonnet for interop with DS that would not be accepted by the main repo for back-porting and we would need to continue to maintain our own custom fork.

Copy link
Contributor

Choose a reason for hiding this comment

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

We didn't do it for IronPython either.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the feedback. I thought of a way to do this without referencing DS Dictionary in Python.NET. What we would do is a two step conversion:

  1. Convert it to a .NET Dictionary, using primitives from Python.NET
  2. Convert the .NET Dictionary to a DS Dictionary, as part of a custom encoder in Dynamo

@aparajit-pratap
Copy link
Contributor

@mmisol thanks for answering my questions and for the detailed enumeration of all possible conversions and limitations.

@mmisol
Copy link
Collaborator Author

mmisol commented Jul 6, 2020

I'll go ahead and merge this. I'll link the task to the PR so that we can take a look whenever we see which of these scenarios we would like to address.

@mmisol mmisol merged commit a898bd0 into DynamoDS:master Jul 6, 2020
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