-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
gh-112632 : Added an option for block formatting to pprint
#129274
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
base: main
Are you sure you want to change the base?
Conversation
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
looks pretty good 👍, but
And please try to make sure CI passes |
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
Could you also add a News entry into the And I think it's a full fledged new feature so this update deserves to be in |
I've added a test case for the new
|
sometimes the problem may not be in you and you need to wait and update your branch (at least it helped me) |
Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst
Outdated
Show resolved
Hide resolved
and don't forget to add news to
|
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
Co-authored-by: donBarbos <donbarbos@proton.me>
I've merged those changes. Thanks for helping me out with that! Is there anything else? |
Let's try to solve problems with |
Co-authored-by: donBarbos <donbarbos@proton.me>
I think we can ping @tomasr8 if you're done making changes. |
Sounds good, I have no more changes to add. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's looking pretty good now! Just two comments:
stream.write(cls.__name__ + '({') | ||
if self._indent_per_level > 1: | ||
stream.write(self._format_block_start(cls.__name__ + '({', indent)) | ||
if self._indent_per_level > 1 and not self._block_style: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not covered by tests (the condition is always False
).
For such a large change, I suggest running coverage
and checking the html report to make sure your tests cover all cases. There's a guide here, but the gist is:
./python -m ensurepip
./python -m pip install coverage
./python -m coverage run --pylib --source=pprint Lib/test/regrtest.py test_pprint
./python -m coverage html -i --include=`pwd`/Lib/* --omit="Lib/test/*,Lib/*/tests/*"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand, what do you mean the case is not covered? The existing tests already covered the case where _block_style
is False
and _indent_per_level
is >1
.
Also when I run the coverage command I don't see anything missing, am I doing something wrong?
python3 -m coverage run --pylib --source=pprint Lib/test/regrtest.py test_pprint
/Users/stodoran/Desktop/cpython/venv/lib/python3.13/site-packages/coverage/inorout.py:486: CoverageWarning: Already imported a file that will be measured: /opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/pprint.py (already-imported)
self.warn(msg, slug="already-imported")
Using random seed: 4261013096
0:00:00 load avg: 4.87 Run 1 test sequentially in a single process
0:00:00 load avg: 4.87 [1/1] test_pprint
== Tests result: SUCCESS ==
1 test OK.
Total duration: 129 ms
Total tests: run=44
Total test files: run=1/1
Result: SUCCESS
python3 -m coverage html -i --include=`pwd`/Lib/* --omit="Lib/test/*,Lib/*/tests/*"
No data to report.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@StefanTodoran if you can't get HTML-based report you can use cli:
$ ./python -m coverage report --show-missing
Name Stmts Miss Branch BrPart Cover Missing
-----------------------------------------------------------
Lib/pprint.py 476 81 182 7 87% 37-46, 57, 67-72, 77, 82, 87-99, 102, 110, 115-116, 172, 174-177, 182, 185, 189, 192-195, 220, 226, 232, 243-245, 262-264, 276-278, 284-286, 293-295, 312-315, 353->326, 367-369, 388-390, 400-402, 409-411, 424-426, 444, 464, 507, 513, 516, 523, 537-539, 546, 556-558, 560-561, 573-575, 595-597, 600-602, 605-607, 610-612, 694, 703, 717->exit
-----------------------------------------------------------
TOTAL 476 81 182 7 87%
I don't know why on the main
branch this line is shown as covered, but this can be solved by adding an explicit pass of indent>1 to the QueryTestCase.test_counter
test, like this:
d = collections.Counter('senselessness')
self.assertEqual(pprint.pformat(d, indent=2, width=1),
"""\
Counter({ 's': 6,
'e': 4,
'n': 2,
'l': 1})""")
and the line will become covered 👍
(unfortunately i can't send you a suggestion as there is no diff nearby, so please add it yourself)
stream.write('[') | ||
stream.write(self._format_block_start('[', indent)) | ||
self._format_items(object, stream, indent, allowance + 1, | ||
context, level) | ||
stream.write(']') | ||
stream.write(self._format_block_end(']', indent)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a lot of repeated code here conditional on self._block_style
. How about defining a context manager to clean this up?
with self._block(stream, indent, '[', ']') as new_indent:
self._format_items(object, stream, new_indent, allowance + 1,
context, level)
pprint
compact=False, sort_dicts=False, underscore_numbers=False, \ | ||
block_style=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are keyword-only (after *
), so we have the luxury of alphabetical sorting:
compact=False, sort_dicts=False, underscore_numbers=False, \ | |
block_style=False) | |
block_style=False, compact=False, sort_dicts=False, \ | |
underscore_numbers=False) |
compact=False, sort_dicts=True, \ | ||
underscore_numbers=False, block_style=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise
compact=False, sort_dicts=True, \ | |
underscore_numbers=False, block_style=False) | |
block_style=False, compact=False, \ | |
sort_dicts=True, underscore_numbers=False) |
If ``True``, | ||
opening parentheses and brackets will be followed by a newline and the | ||
following content will be indented by one level, similar to block style | ||
JSON formatting. This option is not compatible with *compact*. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This option is not compatible with compact.
A passing thought: Perhaps introduce a mode (str) argument, and deprecate compact in favour of it? It's not great to have two conflicting Booleans, though it may be the best option for now.
compact=False, sort_dicts=True, \ | ||
underscore_numbers=False, block_style=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise
compact=False, sort_dicts=True, \ | |
underscore_numbers=False, block_style=False) | |
block_style=False, compact=False, \ | |
sort_dicts=True, underscore_numbers=False) |
compact=False, sort_dicts=True, \ | ||
underscore_numbers=False, block_style=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise
compact=False, sort_dicts=True, \ | |
underscore_numbers=False, block_style=False) | |
block_style=False, compact=False, \ | |
sort_dicts=True, underscore_numbers=False) |
compact=False, sort_dicts=True, underscore_numbers=False, | ||
block_style=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compact=False, sort_dicts=True, underscore_numbers=False, | |
block_style=False): | |
block_style=False, compact=False, sort_dicts=True, | |
underscore_numbers=False): |
pretty-printed json.dumps() when `indent` is supplied. Incompatible | ||
with compact mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pretty-printed json.dumps() when `indent` is supplied. Incompatible | |
with compact mode. | |
pretty-printed json.dumps() when ``indent`` is supplied. | |
Incompatible with compact mode. |
else: | ||
return start_str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else: | |
return start_str | |
return start_str |
else: | ||
return end_str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else: | |
return end_str | |
return end_str |
def _pprint_dataclass(self, object, stream, indent, allowance, context, level): | ||
# Lazy import to improve module import time | ||
from dataclasses import fields as dataclass_fields | ||
|
||
cls_name = object.__class__.__name__ | ||
indent += len(cls_name) + 1 | ||
indent += len(cls_name) + 1 if not self._block_style else self._indent_per_level |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep to 79/80 characters (PEP 8)
Adds a block print option to
pprint
. This option is not compatible with compact. Although the original issue only mentions dictionaries, this implementation implements block style for every datastructure supported bypprint
. I've been testing it with the code in this gist, which is just a bunch of random datastructures filled with dummy data.