Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Provide hook to implement __repr__#808

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
filmor merged 17 commits intopythonnet:masterfromkoubaa:repr
Oct 18, 2019
Merged

Conversation

koubaa
Copy link
Contributor

@koubaakoubaa commentedJan 20, 2019
edited
Loading

Issue: 680

What does this implement/fix? Explain your changes.

This allows C# types to provide__repr__ implementations

Does this close any currently open issues?

680

Any other comments?

Please confirm my expections in the test I added. Inheritance hierarchies in particular were tricky to get right.

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
  • Add yourself toAUTHORS
  • Updated theCHANGELOG

@codecov
Copy link

codecovbot commentedJan 20, 2019
edited
Loading

Codecov Report

Merging#808 intomaster willdecrease coverage by0.28%.
The diff coverage is55.26%.

Impacted file tree graph

@@            Coverage Diff             @@##           master     #808      +/-   ##==========================================- Coverage   76.91%   76.62%   -0.29%==========================================  Files          64       64                Lines        5935     5973      +38       Branches      976      986      +10     ==========================================+ Hits         4565     4577      +12- Misses       1040     1059      +19- Partials      330      337       +7
FlagCoverage Δ
#setup_linux65.3% <ø> (ø)⬆️
#setup_windows75.85% <55.26%> (-0.29%)⬇️
Impacted FilesCoverage Δ
src/runtime/classbase.cs74.8% <55.17%> (-6.57%)⬇️
src/runtime/exceptions.cs79.03% <55.55%> (-1.84%)⬇️
src/runtime/delegatemanager.cs81.96% <0%> (-4.92%)⬇️
src/runtime/pythonexception.cs76.66% <0%> (-3.34%)⬇️

Continue to review full report at Codecov.

Legend -Click here to learn more
Δ = absolute <relative> (impact),ø = not affected,? = missing data
Powered byCodecov. Last update868cd52...82aea1f. Read thecomment docs.

@den-run-ai
Copy link
Contributor

@koubaa one error here:

=================================== ERRORS ====================================___________________ ERROR collecting src/tests/test_repr.py ___________________ImportError while importing test module 'C:\projects\pythonnet\src\tests\test_repr.py'.Hint: make sure your test modules/packages have valid Python names.Traceback:src\tests\test_repr.py:7: in <module>    from Python.Test import (ReprTest)E   ImportError: cannot import name 'ReprTest' from 'Python.Test' (unknown location)!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!

@koubaa
Copy link
ContributorAuthor

@denfromufa How do I run the tests locally? I want to make sure they work before pushing. (I just tested manually in the console and tried to follow the pattern)

@koubaa
Copy link
ContributorAuthor

I figured it out (took longer than I'll admit!)

@koubaa
Copy link
ContributorAuthor

One test fails because therepr of System.OverflowException went from
OverflowException('Simple message..."
to
<System.OverflowException object at 0xADDRESS>

I'll need to figure out how the old behavior was working to see why its broken now.

@den-run-ai
Copy link
Contributor

@koubaa were you able to run the tests locally? If not, then I can search if we have instructions somewhere.

@koubaa
Copy link
ContributorAuthor

@denfromufa yes I can run locally now. I have vs2017 installed and ran this to build:

python setup.py install --xplat

then this to test:

python -m pytest

Should this be in the README?

@den-run-ai
Copy link
Contributor

den-run-ai commentedJan 23, 2019 via email

This is only partial tests, there are also embedding tests run throughnunit.Documentation improvements are welcome, probably this one should go intowiki.
On Tue, Jan 22, 2019, 6:43 PM Mohamed Koubaa ***@***.***> wrote: @denfromufa <https://github.com/denfromufa> yes I can run locally now. I have vs2017 installed and ran this to build: python setup.py install --xplat then this to test: python -m pytest Should this be in the README? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#808 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AHgZ5RkZgmBsugyNIIRfmhr349PPwytMks5vF7BCgaJpZM4aJb9z> .

@koubaa
Copy link
ContributorAuthor

@denfromufa sounds good. I didn't see any embedded test fails in previous CI runs so I'm OK running these partial tests for now.

I tried to find where OverflowExceptionrepr is coming from (on master) and actually no breakpoints in tp_repr defined were hit. So I really don't know (1) how else to look for it and (2) how I could test that its an exception in classbase tp_repr and fallback to python defaults.

@koubaa
Copy link
ContributorAuthor

koubaa commentedFeb 4, 2019
edited
Loading

@denfromufa I am back from a vacation so I looked at this again. I found thischange which removedtp_repr fromExceptionClassObject. After some trial and error I discovered that__repr__() works on master because of what's done inSetArgsAndCause and the fact that a__repr__() was not defined. Now thatClassBase implementstp_repr, the CPython runtime will not fall back to the args/cause which were set.

My plan is to re-implement repr inExceptionClassObject as was done before that change. Please let me know if you have any concerns with this approach.

@koubaakoubaaforce-pushed therepr branch 2 times, most recently from859f80b to8f6bdceCompareFebruary 5, 2019 01:30
@koubaa
Copy link
ContributorAuthor

This is only partial tests, there are also embedding tests run through nunit. Documentation improvements are welcome, probably this one should go into wiki.

I just edited the wiki with what I know about so far.

@koubaa
Copy link
ContributorAuthor

python tests now pass in CI. Embedded tests pass locally (on windows) but not in CI, so I'm adding some logging statements to see where.

@filmorfilmor added this to the2.4.0 milestoneFeb 5, 2019
Copy link
Member

@filmorfilmor left a comment

Choose a reason for hiding this comment

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

Thanks already for your contribution. I have to think a bit about whether the "new"__str__ behaviour is how I would expect things to work.

@koubaa
Copy link
ContributorAuthor

I'm having a lot of trouble with these CI tests.

  • The latest Travisjob is not using my latest changes. Appveyor at least reports the correct SHA1 but have the below errors.
  • Appveyor 2.7 x64 xplat hangs for one hour when about to run embedded tests.
  • Appveyor 3.4 x86 xplat fails in pip install
  • Appveyor 3.4 x64 xplat also fails in pip install
  • Appveyor 2.7 x86 seems to have blown up because of the print statements I added. Is there a reason why Console.WriteLine is crashing (i.e. is stdout unavailable?) and if so what's the preferred way to add this sort of debugging logging statements?
  • Appveyor 2.7 x64 complains of a test failure but I cannot find much more details.
  • Appveyor 3.4 x86 also fails in setuptools
  • Appveyor 3.4 x64 also fails in setuptools.

Since all of the appveyor py3.4 are failing in setuptools it seems to me that its fallen out of maintenance. The 1 hour hangs concern me most since everything is queued and it delays other tests.

@den-run-ai
Copy link
Contributor

@filmor we can probably make python 3.4 optional in CI tests as a temporary solution until we drop it?

@filmor
Copy link
Member

I'll have a look into this this weekend. Could you please remove the debug output?

@koubaa
Copy link
ContributorAuthor

done

@koubaa
Copy link
ContributorAuthor

Seems better but its hard to determine what's wrong with x64 2.7. It says python tests failed but no indication which ones.

@filmor
Copy link
Member

From the logs I think that the issue is aimply the casing of theReprTests.cs. In the repository it's written in camel case, while in the csproj file ot'sreprtests.cs. Correct the csproj and it should go through.

@koubaa
Copy link
ContributorAuthor

@filmor done. Hopefully this works. Do you agree with the newstr behavior()?

@filmor
Copy link
Member

Each dot indicates a successful test, so you can just count ;)

I'll have a look into this as soon as I have finally finished the 2.4.0 release.

@filmorfilmor modified the milestones:2.4.0,2.4.1Apr 12, 2019
@filmorfilmor added the next labelSep 12, 2019
@codecov-io
Copy link

codecov-io commentedSep 12, 2019
edited
Loading

Codecov Report

Merging#808 intomaster willdecrease coverage by2.65%.
The diff coverage isn/a.

Impacted file tree graph

@@            Coverage Diff             @@##           master     #808      +/-   ##==========================================- Coverage   86.71%   84.05%   -2.66%==========================================  Files           1        1                Lines         301      301              ==========================================- Hits          261      253       -8- Misses         40       48       +8
FlagCoverage Δ
#setup_linux65.44% <ø> (ø)⬆️
#setup_windows65.78% <ø> (-5.65%)⬇️
Impacted FilesCoverage Δ
setup.py84.05% <0%> (-2.66%)⬇️

Continue to review full report at Codecov.

Legend -Click here to learn more
Δ = absolute <relative> (impact),ø = not affected,? = missing data
Powered byCodecov. Last update60e6045...264c78b. Read thecomment docs.

@filmor
Copy link
Member

Looks like the problems were magically fixed :)

}

//If the object defines __repr__, call it.
System.Reflection.MethodInfo reprMethodInfo = instType.GetMethod("__repr__");
Copy link
Member

@lostmsulostmsuSep 12, 2019
edited
Loading

Choose a reason for hiding this comment

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

Since all .NET types haveToString, why does it even try__repr__? If somebody really needs it, they can dooverride string ToString() => __repr__()

Copy link
Member

Choose a reason for hiding this comment

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

That's not the same, though.ToString is more akin to__str__, there is no real equivalent to__repr__ in .NET.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, this is thetp_str implementation.tp_repr is below

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

@lostmsu See the comment:
//The return value must be a string object. If a class definesrepr() but notstr(),
//thenrepr() is also used when an “informal” string representation of instances of that
//class is required.

This sentence comes straight from the python manual, I didn't make it up

Copy link
Member

Choose a reason for hiding this comment

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

@koubaa the default inheritance hierarchy for C# classes from Python's point of view is Python'sobject <-System.Object <-CustomCSharpClass.

Since for all .NET classes overridingToString is how you implement__str__, I don't see why it should be different forSystem.Object. Hence I think .NET classes should just always callToString fortp_str.

Copy link
ContributorAuthor

@koubaakoubaaSep 16, 2019
edited
Loading

Choose a reason for hiding this comment

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

@lostmsu I took a look. I agree some kind of consensus between interface vs reflection for dunder methods should be reached and applied throughout the code base. One argument for reflection is that you can use extension methods to add these. If I take an existing C# codebase and write some extension methods in a separate assembly, I can provide__repr__ and__getattr__ to it. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

@koubaa, extension methods would be hard to find. You'd have to enumerate all types in all assemblies.GetMethods won't return them.

In addition to that, what would be the semantics of multiple assemblies defining an extension method with the same signature?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

@lostmsu ah, didn't know that.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

@lostmsu I am still not convinced about the interface approach. It would require a hard build dependency on C# libraries onto PythonNet. It seems like a tough sell for some of the mature C# libraries out there.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

@lostmsu I changed this as you requested. I don't think I can capture the repr function in a Func object since this is a static method.

}

//If the object defines __repr__, call it.
System.Reflection.MethodInfo reprMethodInfo = instType.GetMethod("__repr__");
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, this is thetp_str implementation.tp_repr is below

Copy link
ContributorAuthor

@koubaakoubaa left a comment

Choose a reason for hiding this comment

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

Looks like the problems were magically fixed :)

This is equal parts annoying and relieving

}

//If the object defines __repr__, call it.
System.Reflection.MethodInfo reprMethodInfo = instType.GetMethod("__repr__");
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

@lostmsu See the comment:
//The return value must be a string object. If a class definesrepr() but notstr(),
//thenrepr() is also used when an “informal” string representation of instances of that
//class is required.

This sentence comes straight from the python manual, I didn't make it up

@filmor
Copy link
Member

To help you in disagreeing, I propose the another style: We add a new generic abstract class (or interface with default methods when we convert to C#8)PythonWrapper and allow it to be registered for automatic conversion:

using SomeLib;[Python.Conversion]public class SomeClassWrapper : PythonWrapper<SomeClass> {    public string Repr() => $"<SomeClass {this.wrapped.Name}>";}

Now this means that we would need to linkPython.Runtime.dll (or a much smaller DLL that is only used for these markers and the interface) into the wrapper DLL, but this is not an issue in embedding situations and everywhere else we could use the mentioned "smaller", platform-independent DLL.

@lostmsu
Copy link
Member

@filmor not sure I understood your proposal.
Can you give a more complete example? What shouldPythonWrapper<T> do?

@koubaa
Copy link
ContributorAuthor

Hey, can this go in yet?

@filmorfilmor merged commit4a9457f intopythonnet:masterOct 18, 2019
@filmor
Copy link
Member

It can, thanks a lot for your contribution :)

@lostmsulostmsu modified the milestones:2.4.1,2.5.0Apr 23, 2020
Runtime.PyTuple_SetItem(args, 0, ob);
IntPtr reprFunc = Runtime.PyObject_GetAttrString(Runtime.PyBaseObjectType, "__repr__");
var output = Runtime.PyObject_Call(reprFunc, args, IntPtr.Zero);
Runtime.XDecref(args);
Copy link
Contributor

Choose a reason for hiding this comment

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

Decreasing args reference count actually decreases ob reference count, which marks it as garbage for the GC!
After a while GC frees the object which causes the program to crash if the object is used again.
One fix for this can be adding the line:
Runtime.XIncref(ob);
at line 269 (before setting ob to the tuple's first argument).

filmor reacted with thumbs up emoji
Copy link
Member

Choose a reason for hiding this comment

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

Thanks a lot for catching this. Would you prepare a small PR?

Copy link
Contributor

Choose a reason for hiding this comment

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

Done
1160

AlexCatarino pushed a commit to QuantConnect/pythonnet that referenced this pull requestJun 27, 2020
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@filmorfilmorfilmor left review comments

@amos402amos402amos402 left review comments

@DanBarzilianDanBarzilianDanBarzilian left review comments

@lostmsulostmsulostmsu approved these changes

Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
2.5.0
Development

Successfully merging this pull request may close these issues.

7 participants
@koubaa@den-run-ai@filmor@codecov-io@lostmsu@amos402@DanBarzilian

[8]ページ先頭

©2009-2025 Movatter.jp