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
Consistent __repr__ and __str__ methods for all types #884
Conversation
Codecov Report
@@ Coverage Diff @@
## master #884 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 16 16
Lines 2716 2742 +26
Branches 518 521 +3
=====================================
+ Hits 2716 2742 +26
Continue to review full report at Codecov.
|
I've looked but can't find any official (or quasi-official) guidance on what format or data should be used in Instead I looked a some big projects like numpy and django and did something simpler and sensible. |
@samuelcolvin I'll think some more about the repr vs. str question, but really quickly: is there a good reason we show when a secret str is empty? Feels like a potential risk, since in that case we show the exact value of the string. I've been meaning to ask this for a while (and seeing it in this PR reminded me), and I can create a separate issues to discuss, but figured there might be a brief answer. |
@samuelcolvin The official docs for repr say:
Based on this, I think it might be reasonable to drop the angle brackets in some instances (e.g., for BaseModel subclasses). Obviously the generated string wouldn't be eval-compatible in all cases (e.g., if the field type can't generate an eval-compatible repr), but it would mean that when it was compatible, the repr would look as nice as possible. It seems to me that for most models, this change would make the repr output eval-compatible, and I think that would help make it feel more intuitive for new users. I think it's fine if one of the field values isn't repr-friendly, and results in having an angle-bracket value printed inside the repr; I just don't think that means we should (necessarily) avoid the cleaner form entirely. |
To make my suggestion more concrete: Version currently proposed in this PR: assert repr(m) == "<Model(v=[<SubModel(name='testing' count=4)>])>" Version I'm proposing in the above comment: assert repr(m) == "Model(v=[SubModel(name='testing', count=4)])" |
My suggestion would be to handle from pydantic import SecretStr, BaseModel
class Model(BaseModel):
secret: SecretStr
print(str(Model(secret='abc')))
# Model(secret=SecretStr('**********'))
print(repr(Model(secret='abc')))
# Model(secret=<SecretStr('**********')>) |
I agree with everything except:
This is wrong IMHO:
In other words: even though you're calling |
@dmontagu I've made changes as per your suggestions, as well as doing some work to integration with python-devtools. Let me know what you think. |
You were totally right about the str vs represent for arguments. |
Code quality improved in this PR IMO, all goodness |
Looks good to me |
* Consistent __repr__ and __str__ methods for all types * add change description * devtools integration and feedback on repr methods * fix Color repr * tests for truncate * add devtools section to docs * tests for devtools * ValidationError inheriting from Representation * fix imports * tweaks * tweak docs * exec_examples.py integration with __repr__ changes
Change Summary
Consistent
__repr__
and__str__
method for all models, in general:__str__
returns a human readable string representing the data the instances holds. Defined as something like "what you might show to an end user if you were lazy"__repr__
is roughlyf'ClassName({str(self)})'
, except commas are used in separators to makeeval(repr(m))
roughly equal to mother changes:
__pretty__
method added to integrate with python-devtoolsdisplay()
method onSecretStr
andSecretBytes
has been depreciated in favour of `str(s)to_string()
method onBaseModel
has been depreciated in favour ofstr(model)
, devtools is a much better approach.This is a bigger than I had hoped for during v1 betas, however users have done something seriously wrong if they're parsing the output of
str(x)
orrepr(x)
and I think this is much better than what went before.This can't be merged until either all docs examples changed, or we setup an automatic way of generating the print output in examples (I'm going to work on this).
Checklist
changes/<pull request or issue id>-<github username>.md
file added describing change(see changes/README.md for details)