-
Notifications
You must be signed in to change notification settings - Fork 987
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
Reformat the code with black #3367
Conversation
This has two commits, the first one is the actual logical changes to make |
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 like it. I'm already using black
locally so adding it here makes things easy for me. Guess I'll be making the switch to 88 character line widths...
This is probably blocked on psf/black#64 and psf/black#22 to be resolved before we can use this. |
This now has some manual reformatting (prior to the |
Comment from @sigmavirus24 on the list:
|
I'm very happy you're testing Black. I would wait a while before jumping in, at least until beta 1. I will let you know as soon as the current blockers are resolved. |
Thanks, @ambv. @njsmith on the mailing list recommends we consider yapf. My suggestion: @dstufft could redo this PR so we retain the code reformatting but take out the dependence on |
I'd rather not merge a bunch of formatting changes without a mechanism to ensure things stay consistent going forward. Merging this will conflict with open PRs, that's OK if the pay off is "then you never have to think about formatting again", but less so if the pay off is just "and now things are formatted differently". |
I agree with Donald. Wait a few more days, the main two missing pieces in Black are:
I want to get to the first within the next few days and tackle the other over the weekend. Hopefully the reformatting of Warehouse then will prove good enough to adopt the tool. Afterwards, barring small bugs, we will only be left with one planned feature that's currently missing: standardizing all strings to double quotes (unless those introduce escapes). This is needed to minimize backslash escaping and to be able to join |
I skimmed the |
Ah, there's another blocker to this too that I forgot to mention: psf/black#67. The outcome of which will likely decide whether I'm willing to actually use black on this code base or not. I've detailed some more specific thoughts at psf/black#67 (comment). I mentioned it in the comment thread on black, but I want to re-iterate since this issue is linked from black's repository now and folks have sometimes tried to use my statements as cudgels against other projects. I think it is perfectly acceptable and fine if black decides to go in a way that makes me unwillingly to use it for this specific repository. Opinionated projects will always sometimes not be the right fit, or produce worse results, for some circumstances and if the opinions of black end up making that true for Warehouse, that is perfectly OK. Of course I do hope we can use it here, but the decision of what opinions black has is up to the black project, not me. |
I've updated the pinned version of black in this PR, removed the manual formatting tweaks I had to do to satisfy the other bersion, and reformatted the project using black 18.4a2 to give folks a chance to poke around the way black would currently format the project and see if they see any major issues with readability or what have you. This version still does not pass our normal linter (when relaxed to 88 characters) for two lines of code:
The first of these errors is a block of code that looks like: def test_includeme():
...
assert (
config_settings
== {
"jinja2.filters": {
"format_date": "warehouse.i18n.filters:format_date",
"format_datetime": "warehouse.i18n.filters:format_datetime",
"format_rfc822_datetime": "warehouse.i18n.filters:format_rfc822_datetime",
"format_number": "warehouse.i18n.filters:format_number",
}
}
) The line that fails is the longest line in the dictionary, the one for the key Playing around with it a little bit, it appears that you can get it to give you better behavior by wrapping with parentheses: def test_includeme():
...
assert (
config_settings
== {
"jinja2.filters": {
"format_date": "warehouse.i18n.filters:format_date",
"format_datetime": "warehouse.i18n.filters:format_datetime",
"format_rfc822_datetime": (
"warehouse.i18n.filters:format_rfc822_datetime"
),
"format_number": "warehouse.i18n.filters:format_number",
}
}
) That feels like a bug with black though, since AIUI it's not supposed to care about the already existing formatting at all, and it should have already injected those parens. I wonder if @ambv would be willing to chime in about if that is a bug or not? The other bit is code that looks like this: def cache_control(
seconds, *, public=True, stale_while_revalidate=None, stale_if_error=None
):
def inner(view):
@functools.wraps(view)
def wrapped(context, request):
response = view(context, request)
if not request.registry.settings.get("pyramid.prevent_http_cache", False):
if seconds:
if public:
response.cache_control.public = True
else:
response.cache_control.private = True
response.cache_control.stale_while_revalidate = stale_while_revalidate
response.cache_control.stale_if_error = stale_if_error
response.cache_control.max_age = seconds
else:
response.cache_control.no_cache = True
response.cache_control.no_store = True
response.cache_control.must_revalidate = True
return response
return wrapped
return inner The line that fails is the def cache_control(
seconds, *, public=True, stale_while_revalidate=None, stale_if_error=None
):
def inner(view):
@functools.wraps(view)
def wrapped(context, request):
response = view(context, request)
if not request.registry.settings.get("pyramid.prevent_http_cache", False):
cache_control = response.cache_control
if seconds:
if public:
cache_control.public = True
else:
cache_control.private = True
cache_control.stale_while_revalidate = stale_while_revalidate
cache_control.stale_if_error = stale_if_error
cache_control.max_age = seconds
else:
cache_control.no_cache = True
cache_control.no_store = True
cache_control.must_revalidate = True
return response
return wrapped
return inner Is a perfectly reasonable change to make to keep the lines shorter. |
Manual tweaks from above have been added in 3cfc497 to keep them separate. |
Poking around, I've found a few more potential issues from looking at the output produced by black: psf/black#153, psf/black#152. Everything else though is look pretty fine to me. Some of it I would have done differently, but part of the point of using black is to stop having nit-picky code local opinions ;) |
Thanks for testing it! I hope this is going to be mergeable soon! Managing parentheses is a long subject. tl;dr - I can't always add or remove them automatically. Do it yourself and Black will keep it. It will become smarter about this in the future. Longer explanationParentheses aren't entirely "existing formatting". Sometimes they are are needed just for human readability. Examples include:
The formatter cannot decide whether something is easy or hard to read by humans so it doesn't remove those sorts of parentheses. In fact, for one-tuples, it's always adding them because they sometimes hid bugs. Currently there's five kinds of expressions where Black will automatically manage parentheses:
That means it will add and remove parens based on whether they're needed or not in those cases. I could easily add support for this also around dictionary values and assignments. This would solve both of your issues reported above. However, I'm not entirely happy with what Black is doing with automatic parentheses. Since the algorithm is deliberately simple, it puts extra newlines in ways that human programmers wouldn't. Your So, before I add automatic management of parentheses in assignments and dictionary values, I need to improve how Black is formatting code in this case. (This will also improve formatting in cases like your In the mean time, as you observed, putting parentheses manually works around the problem. |
@ambv Ah okay, that makes sense! It also means that I'm probably going to have to format the files with black one at a time so I can actually review the diff of each file and make sure we're not introducing something crummy that can be solved by adding parentheses. That is more work, but not unreasonable (and it's really only meaningfully new work for me on this PR because we're reformatting such a large bunch of code, instead of just the smaller bit we've recently added). Thanks a lot for all your help thus far! |
cffd7ae
to
80c02fc
Compare
This should be ready now! I'd love to get @ewdurbin and @di to look at it to make sure they are happy with how things are formatting. There are a couple of known issues which are (reasonable) limitations in black combined with some structure of the code that already exists. These will largely just require going through and doing some manual tweaking. The big one that I'm aware of is that black does not automatically combine string literals (because it would produce different AST). So in cases where we used to have something like: foo = (
"This is a "
"string."
) black then correctly combined that to a single line that looks like: foo = "This is a " "string." I've opt'd not to fix that in this PR, because this PR is hard to keep up to date as changes land and I have to rebase it. It's not bad if I can just blow away the reformat commit and reformat again, but if I have to re-apply manual tweaks each time that gets much more diifficult. Additional PRs can clean up the cases where we can get a better result out of black with some manual restructuring. All in all, I am in favor of this PR and would like to get it landed. |
This is exciting :-) |
I'm going to go ahead and merge this, Ernest is out and I believe he's already been +1 on this in general. |
No description provided.