Skip to content

Allow repr (+ str?) to take callables #212

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

Closed
Julian opened this issue Jun 15, 2017 · 11 comments · Fixed by #568
Closed

Allow repr (+ str?) to take callables #212

Julian opened this issue Jun 15, 2017 · 11 comments · Fixed by #568
Labels

Comments

@Julian
Copy link
Member

Julian commented Jun 15, 2017

It would be useful to be able to pass in a callable to do repr'ing of attributes.

For me this happens if I want to present a value in the repr differently than just repr(foo), which is sometimes useful, especially if the "different way" is to use e.g. reprlib.repr to do auto-truncation of long values.

Being able to pass in callables to the repr argument seems at first glance like a reasonably easy way to do that.

E.g.

attr.ib(repr=reprlib.repr)

and

attr.ib(repr=lambda value: repr(value) * 12)

You could preserve backwards compatibility by having True be equivalent to repr, and False be a sentinel (which you need anyways).

I think this could also satisfy #41, if you do the same to attr.s, and then provide an attr.simple_repr, so you'd do attr.s(repr=attr.simple_repr) and get the normal bracket repr instead of the eval one.

@blueyed
Copy link
Member

blueyed commented Jul 31, 2017

See #224 (comment) for a patch to support a callable with repr.

@Tinche
Copy link
Member

Tinche commented Jul 31, 2017

This is an interesting idea.

I think our repr support can be improved in any case; we're doing more work in the method that is generally needed, so it can be sped up by eval-ing a tailored function. Part of this work can be changing the Attribute.repr type to essentially be Union[bool, Callable[[], str] (so, either a boolean or a callable) and applying the callable when __repr__-ing.

@The-Compiler
Copy link
Contributor

Another use case where this is useful are numbers which you'd like to show in hexadecimal (modifiers = attr.ib(repr=lambda mod: hex(int(mod))), or PyQt (not Python) enum values where you want to get a human-readable value instead of an int.

@nvgoldin
Copy link

nvgoldin commented Feb 4, 2018

Another use case I have is when you have a list attribute and you'd like __repr__ to print out only the list length (for example in cases where it is extremely large).

Would be happy to know if there is another way to do it.

@gimbo
Copy link

gimbo commented Jun 15, 2018

I've created a small extension which provides callable reprs and allows titles to be overridden too (e.g. for the length case cited above): attrs_flexible_reprs.py

Input/feedback welcomed.

@hynek
Copy link
Member

hynek commented Jun 16, 2018

@gimbo I think your flexible repr doesn’t take into account our recursion handler?


Re earlier comments, I wouldn’t make this issue depend on transforming our repr generator to code generation. It would be nice to have, but not required for fixing this particular issue.

@gimbo
Copy link

gimbo commented Jun 18, 2018

@hynek I'm sure you're right - it's very simplistic, just the simplest thing I came up with that scratched the itch I had.

I haven't delved into the code of attrs at all - when you say "recursion handler" I'm guessing you mean something to handle the case where a class A has a field also of type A? Certainly my code doesn't handle that gracefully, it seems. Perhaps I'll take a look at what attrs does by default and try to upgrade. :-) Thanks!

@hynek
Copy link
Member

hynek commented Jun 18, 2018

Glyph has recently taught our repr to detect loops in definitions so it doesn’t run into max recursion error. You'd have to look at the current code and shoehorn the callable thing into it.

@wbolster
Copy link
Member

wbolster commented Sep 6, 2019

This is similar (identical?) to #567, and #568 adds support for this.

@hynek
Copy link
Member

hynek commented Sep 6, 2019

Took only two years!!!1!

@blueyed
Copy link
Member

blueyed commented Sep 19, 2019

@hynek
Almost like good wine!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants