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

bpo-43080: pprint for dataclass instances #24389

Merged
merged 11 commits into from
Apr 13, 2021

Conversation

LewisGaul
Copy link
Contributor

@LewisGaul LewisGaul commented Jan 31, 2021

@LewisGaul
Copy link
Contributor Author

LewisGaul commented Jan 31, 2021

I've realised this doesn't respect user-defined __repr__() methods. I wasn't able to use the existing mechanism of comparing the IDs of __repr__ in the _dispatch dict as dynamically created __repr__s all have different IDs.

The best solution to this I can think of is to check object.__repr__.__module__ - this seems to be 'dataclasses' if defined by the dataclass machinery. I'm not sure how watertight this solution is though?

EDIT: This solution doesn't work on master actually...

@github-actions
Copy link

github-actions bot commented Mar 3, 2021

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale Stale PR or inactive for long period of time. label Mar 3, 2021
@Mariatta Mariatta requested a review from ericvsmith March 3, 2021 00:41
Copy link
Member

@ericvsmith ericvsmith left a comment

Choose a reason for hiding this comment

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

I'm still not convinced this is an awesome idea, but see my review comments anyway.

@LewisGaul
Copy link
Contributor Author

I'm still not convinced this is an awesome idea, but see my review comments anyway.

I'm happy to address the comments, but if we're not expecting it to be merged shall we just close the PR? I would like to see this feature make it into core, but I won't be offended if you're against it overall, and better not to waste time fixing stuff up if it's not going in anyway! :)

@github-actions github-actions bot removed the stale Stale PR or inactive for long period of time. label Mar 16, 2021
@LewisGaul
Copy link
Contributor Author

LewisGaul commented Mar 20, 2021

I've realised this doesn't respect user-defined __repr__() methods. I wasn't able to use the existing mechanism of comparing the IDs of __repr__ in the _dispatch dict as dynamically created __repr__s all have different IDs.

I've added a failing testcase to track this issue.

@ericvsmith Do you have any thoughts on how best to tackle this? You suggested the following on the issue, is this approach worth pursuing here?

Adding an attribute on the __repr__ (and other methods?) signifying that they were generated would let us distinguish them.

Say, checking getattr(__repr__, '__is_generated__', False), or similar.

@ericvsmith
Copy link
Member

For the __repr__ check, how about examining __repr__.__qualname__ and checking for __create_fn__.<locals>.__repr__? I think that's a sufficiently unlikely string that it could be used. Although it's an implementation detail and probably a fragile test, I'd be okay with using it inside the stdlib. Or we could change the name of __create_fn__ to __dataclasses_create_fn__ to reinforce the fact that this is a dataclasses internal.

@LewisGaul
Copy link
Contributor Author

For the __repr__ check, how about examining __repr__.__qualname__ and checking for __create_fn__.<locals>.__repr__? I think that's a sufficiently unlikely string that it could be used. Although it's an implementation detail and probably a fragile test, I'd be okay with using it inside the stdlib. Or we could change the name of __create_fn__ to __dataclasses_create_fn__ to reinforce the fact that this is a dataclasses internal.

I see what you're suggesting when trying it out on 3.8, but it seems the qualname was 'fixed' in #22155, so this approach won't work on master. Any other ideas/preferences? :)

@ericvsmith
Copy link
Member

I see what you're suggesting when trying it out on 3.8, but it seems the qualname was 'fixed' in #22155, so this approach won't work on master. Any other ideas/preferences? :)

You could do the same with __repr__.__wrapped__:

<function __create_fn__.<locals>.__repr__ at 0x0000022FF4824670>

Check that __wrapped__ exists and contains "__create_fn__".

Again, it's super fragile, but since both modules are in the stdlib and will be tested to work together, I'm not so concerned.

@ericvsmith
Copy link
Member

Again, it's super fragile, but since both modules are in the stdlib and will be tested to work together, I'm not so concerned.

And you can blame me in a comment if you want!

@LewisGaul
Copy link
Contributor Author

@ericvsmith this should be good for second review/merge now :)

@ericvsmith
Copy link
Member

@LewisGaul : I'm planning on fixing a bug (which I can't find right now) dealing with repr of recursive dataclasses. I'm going to hold off on this until that one is merged, at which point we can do the same fix here. But if you haven't heard from me in a week or so, please ping me again.

@ericvsmith
Copy link
Member

@LewisGaul : Can you add support and tests for recursive dataclasses? See

def test_recursive_repr(self):

@LewisGaul
Copy link
Contributor Author

@ericvsmith I've added handling for recursive dataclasses. Note that this required some special-casing (to avoid backwards incompatibility of formatting other recursive objects), where the existing handling in the pprint module would have given the following:

dataclass4(a=<Recursion on dataclass4 with id=2119600742448>)

Copy link
Member

@ericvsmith ericvsmith left a comment

Choose a reason for hiding this comment

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

One last request for a cyclical test.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@LewisGaul
Copy link
Contributor Author

I have made the requested changes; please review again.

I don't think the CI failures are related (test_ssl failure on macOS, docs build failure).

@bedevere-bot
Copy link

Thanks for making the requested changes!

@ericvsmith: please review the changes made to this pull request.

@LewisGaul
Copy link
Contributor Author

Thanks for taking the time to review @ericvsmith :) Is there anything else I need to do before this can be merged?

@ericvsmith
Copy link
Member

@LewisGaul : No, nothing else. I'll try and finish up my final review and push of this tonight. Thanks for your patience.

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.

4 participants