asottile / add-trailing-comma Goto Github PK
View Code? Open in Web Editor NEWA tool (and pre-commit hook) to automatically add trailing commas to calls and literals.
License: MIT License
A tool (and pre-commit hook) to automatically add trailing commas to calls and literals.
License: MIT License
This is probably a strange ask, but I am working on a project that requires all trailing commas in Python code to be removed. I was wondering if there was a way to achieve that goal with a few tweaks to this codebase?
I haven't looked very closely at the code, but I figured I would ask first to save myself some time if it was infeasible. Thanks!
This utility adds trailing comma to function call having a single param - yes, this is in line with the overall idea - however, I find it quite ugly.
IMO it would be useful to skip trailing comma in cases like below. Can this be controlled by an additional parameter?
logger.warning(
f"Retry needed for http request, sleeping {wait_time} seconds.",
)
I would like to use add-trailing-comma to add trailing commas to a file. However add-trailing-commas also adds and removes whitespace. Is it possible to disable whitespace editing?
Here's an (admittedly poorly-formatted) reproduction. FWIW I prefer add-trailing-comma's approach, but curious to hear your thoughts. This is obviously weird indentation but ideally they wouldn't fight. Do we need to make autopep8 smarter?
[a()
for b in c
if (
d
)
]
[a()
for b in c
if (
d
)
]
As of recent update, Kotlin supports trailing commas. I wonder if it would be possible to use this tool to add trailing commas all over Kotlin/Android project?
x = ([a,
b], None)
gets rewritten to this:
x = (
[
a,
b,
],
, None
)
which is invalid syntax:
File "test.py", line 6
, None
^
SyntaxError: invalid syntax
(with version 0.6.0)
Interpreter: Python 3.10
Minimum breaking example:
match 1:
case str(): # `str()` seems to be important here!
pass
case _:
pass
Probably related to #177 .
Not sure if this is intended behavior, but here's an example:
- take(TAB_ENTRIES_COUNT, find_matches(
- entries,
- [tab_needle],
- check_entries=False)),
- TAB_SEPARATOR)
+ take(
+ TAB_ENTRIES_COUNT, find_matches(
+ entries,
+ [tab_needle],
+ check_entries=False,
+ ),
+ ),
+ TAB_SEPARATOR,
I would have expected something like this instead:
print_tab_menu(
tab_needle,
take(
TAB_ENTRIES_COUNT,
find_matches(
entries,
[tab_needle],
check_entries=False,
),
),
TAB_SEPARATOR,
)
First of all, I want to say thank you for add-trailing-comma
. It's a very good addition to black
and isort
and eliminates the need to think about the code style.
The only inconvenience is the lack of a configuration file. In some projects we have files or even directories we want to exclude from add-trailing-comma
. We have to use custom scopes for watcher tasks in PyCharm and filter files in GitHub CI actions for add-trailing-comma
. In the same time, black
and isort
can be easily configured via pyproject.toml
.
I'm wondering do you have plans to implement this feature and how can I help with it?
I think the following would be some good enhancements to this tool:
--diff
like isort, which prints the suggested changes on stdout, instead of modifying the files.
This is great for CI checks where a contributor gets to see the required changes to fix the situation directly.
--recursive
option, to specify an entire project directory without globs.
This would make CLI invocations easier.
I'll be happy to write PRs for them if @asottile thinks they're reasonable.
In the example below, a trailing comma is not added. Is this international, or might this be a bug?
dict = {"variable_1": 1, "variable_2": 2}
This should be a noop:
x = y.\
foo(
bar,
)
However, this is the current behaviour:
x = y.\
foo(
bar,
- )
+)
Might need help from asottile/tokenize-rt#1
I'm using yapf in VSC. I find that YAPF reverts changes made by the pre-commit hook:
So when finished with a change, I commit the changes, but then the pre-commit hook undoes the changes, requiring me to add the new changes another time to the staged files.
Not a real issue as such, but I'm wondering if there is a more elegant way to handle this.
I'm not really experienced, so I fully realize that the issue is likely on my end...
(Wasn't sure how to describe this scenario better, sorry for the lame title.)
Here's a fairly minimal example:
(
a
).thing(b)
Produces an error when processing with add-trailing-comma v0.2.0:
Traceback (most recent call last):
File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/bin/add-trailing-comma", line 9, in <module>
load_entry_point('add-trailing-comma==0.2.0', 'console_scripts', 'add-trailing-comma')()
File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 269, in main
ret |= fix_file(filename, args)
File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 249, in fix_file
contents_text = _fix_commas(contents_text, args.py35_plus)
File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 232, in _fix_commas
_fix_call(call, i, tokens)
File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 189, in _fix_call
paren_stack.pop()
IndexError: pop from empty list
def a():
with b(c), \
d(
e,
):
pass
def a():
with b(c), \
d(
e,
):
pass
gross :(
with a:
pass
[b] = {1}
produces this error with add-trailing-comma version 0.5.1:
Traceback (most recent call last):
File "/nail/home/ckuehl/.pre-commit/repo3dPrz7/py_env-python2.7/bin/add-trailing-comma", line 9, in <module>
load_entry_point('add-trailing-comma==0.5.1', 'console_scripts', 'add-trailing-comma')()
File "/nail/home/ckuehl/.pre-commit/repo3dPrz7/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 378, in main
ret |= fix_file(filename, args)
File "/nail/home/ckuehl/.pre-commit/repo3dPrz7/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 358, in fix_file
contents_text = _fix_src(contents_text, args.py35_plus)
File "/nail/home/ckuehl/.pre-commit/repo3dPrz7/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 333, in _fix_src
fixes.append((True, _find_simple(i, tokens)))
File "/nail/home/ckuehl/.pre-commit/repo3dPrz7/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 154, in _find_simple
raise AssertionError('Past end?')
AssertionError: Past end
We are using add-trailing-comma
for dangling commas and isort
to keep our imports organized. Ideally, both can run as pre-commit hooks. However, the two tools clash on statements like this:
from my_library.api.database.models import (Model1, Model2, Model3, Model4, Model5, Model6
Model7,)
where isort
prefers this style and add-trailing-comma
reformats it into:
from my_library.api.database.models import (
Model1, Model2, Model3, Model4, Model5, Model6
Model7,
)
When trying to commit, no matter the order between isort
and add-trailing-comma
, the imports are always re-arranged, preventing commit. Disabling add-trailing-comma
on imports would allow us to run isort and to use your tool for other parts of the file.
I wanted to do this over my entire codebase, but when I run:
pre-commit run --all-files
it returns (no files to check) Skipped
Doesn't really break the code (at least in my case), but looks like a bug:
logger.info(
'one'
- 'two'
+ 'two',
)
I ran into the following error when committing:
VSCode console output:
> git -c user.useConfigOnly=true commit --quiet --allow-empty-message --file -
Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Passed
Check docstring is first.................................................Passed
Debug Statements (Python)................................................Passed
Fix requirements.txt.................................(no files to check)Skipped
Check for added large files..............................................Passed
Check python ast.........................................................Passed
Check builtin type constructor use.......................................Passed
Check for case conflicts.................................................Passed
Detect Destroyed Symlinks................................................Passed
Check for merge conflicts................................................Passed
Check Yaml...........................................(no files to check)Skipped
Debug Statements (Python)................................................Passed
Detect Private Key.......................................................Passed
fix UTF-8 byte order marker..............................................Passed
Add trailing commas......................................................Failed
- hook id: add-trailing-comma
- exit code: 1
Traceback (most recent call last):
File "c:\program files\python39\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "c:\program files\python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "C:\Users\navdh\.cache\pre-commit\repoy6phnb7j\py_env-python3.9\Scripts\add-trailing-comma.EXE\__main__.py", line 7, in <module>
File "c:\users\navdh\.cache\pre-commit\repoy6phnb7j\py_env-python3.9\lib\site-packages\add_trailing_comma.py", line 498, in main
ret |= fix_file(filename, args)
File "c:\users\navdh\.cache\pre-commit\repoy6phnb7j\py_env-python3.9\lib\site-packages\add_trailing_comma.py", line 470, in fix_file
contents_text = _fix_src(contents_text, args.py35_plus, args.py36_plus)
File "c:\users\navdh\.cache\pre-commit\repoy6phnb7j\py_env-python3.9\lib\site-packages\add_trailing_comma.py", line 401, in _fix_src
tokens, _find_call(call, i, tokens),
File "c:\users\navdh\.cache\pre-commit\repoy6phnb7j\py_env-python3.9\lib\site-packages\add_trailing_comma.py", line 239, in _find_call
raise AssertionError('Past end?')
AssertionError: Past end?```
Platform: Windows 10 21H1 OS Build 19043.906
Python Version: 3.9.1
My config:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-docstring-first
- id: debug-statements
- id: requirements-txt-fixer
- id: check-added-large-files
- id: check-ast
- id: check-builtin-literals
- id: check-case-conflict
- id: destroyed-symlinks
- id: check-merge-conflict
- id: check-yaml
- id: debug-statements
- id: detect-private-key
- id: fix-byte-order-marker
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.0.1
hooks:
- id: add-trailing-comma
args: [--py36-plus]
They should be ignored, this currently introduces trailing whitespace:
x('foo', (
'bar',
'baz',
))
Hi, thanks for the great tool!
I recently came across some behaviour that surprised me - I'm not sure if it's a bug or a misunderstanding on my part.
Where df
is a pandas DataFrame and s
is a pandas Series, the following snippet
df.loc[s, ]
gets converted to
df.loc[s,]
(note that the whitespace between the comma and the ]
has been removed). Per https://github.com/asottile/add-trailing-comma#remove-unnecessary-commas, I expected the result to be
df.loc[s]
If you can clear up my confusion I would appreciate it, thank you.
(Aside: the current result causes flake8 to raise E231 Missing whitespace after ',', ';', or ':'
.)
Pre-commit config:
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.1.0
hooks:
- id: add-trailing-comma
args: [--py36-plus]
caused by tokenize-rt 3.0.0, being reverted here: asottile/tokenize-rt#23
if True:
if True:
pass
x = (
1,
)
x = (
1,
- )
+)
write a test to prevent this regression
Seems I broke this in 0.4.3 because now the first function is being considered:
f({}).y(
x
)
should add a comma on the x
line.
If I have a single argument to a function, I would like add-trailing-comma
to not try to add a trailing comma to that argument when doing so means rewriting the overall indentation.
For example:
# this is left alone
the_list.append(Thing(x, y, z))
# but this is changed
the_list.append(Thing(
x,
y,
z,
))
# into this
the_list.append(
Thing(
x,
y,
z,
),
)
I realise that it's a bit of an odd case, however I've found that the vertical style works really well as part of a style guide which aims to minimise diffs. (I use flake8-commas
, which is already aware of this case and doesn't error about it)
I was a little surprised that add-trailing-comma
changes this case as I consider it the same as the first case (all on one line).
Would it be possible to add an option to ignore cases where there is a single argument and it is formatted in this manner?
For clarity: if the code is already in the third form, but just missing the trailing comma, I think it would still be useful to add one there.
ran into the following issue using the add-trailing-comma hook on macOS with python3.9 (works fine with <= 3.8
). .pre-commit-config.yaml
is the one from pre-commit.
i tried reinstalling python3.9 and cleaning the pre-commit cache but nothing changed.
error and system info:
+ sw_vers
ProductName: macOS
ProductVersion: 11.1
BuildVersion: 20C69
+ python --version
Python 3.9.1
+ pre-commit --version
pre-commit 2.9.3
+ pre-commit run add-trailing-comma --all-files
Add trailing commas......................................................Failed
- hook id: add-trailing-comma
- exit code: 1
Traceback (most recent call last):
File "/Users/paulhfischer/.cache/pre-commit/repothj9r_n4/py_env-python3.9/bin/add-trailing-comma", line 8, in <module>
sys.exit(main())
File "/Users/paulhfischer/.cache/pre-commit/repothj9r_n4/py_env-python3.9/lib/python3.9/site-packages/add_trailing_comma.py", line 498, in main
ret |= fix_file(filename, args)
File "/Users/paulhfischer/.cache/pre-commit/repothj9r_n4/py_env-python3.9/lib/python3.9/site-packages/add_trailing_comma.py", line 470, in fix_file
contents_text = _fix_src(contents_text, args.py35_plus, args.py36_plus)
File "/Users/paulhfischer/.cache/pre-commit/repothj9r_n4/py_env-python3.9/lib/python3.9/site-packages/add_trailing_comma.py", line 401, in _fix_src
tokens, _find_call(call, i, tokens),
File "/Users/paulhfischer/.cache/pre-commit/repothj9r_n4/py_env-python3.9/lib/python3.9/site-packages/add_trailing_comma.py", line 239, in _find_call
raise AssertionError('Past end?')
AssertionError: Past end?
a contrived example:
def f[
- T
+ T,
](x: T) -> T:
return x
I have some code that black formatted like this
actual
extended_retry_message = textwrap.dedent(
f"""\
{retry_message[0]}
{retry_blurb}
"""
) # noqa: N400
expected
extended_retry_message = textwrap.dedent(
f"""\
{retry_message[0]}
{retry_blurb}
""",
) # noqa: N400
another
actual
assert all(
(
v == result["new_expectations"][k]
for k, v in {
"jenkins_id": jn.jenkins_id,
}.items()
)
)
expected
assert all(
(
v == result["new_expectations"][k]
for k, v in {
"jenkins_id": jn.jenkins_id,
}.items()
),
)
i have add-trailing-comma running right after black with --py36-plus
and it doesnt add the trailing comma to that function call
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.2.1
hooks:
- id: add-trailing-comma
args: [--py36-plus]
System info:
Pre-Commit config:
repos:
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.2.1
hooks:
- id: add-trailing-comma
Minimum breaking example
a = 'a'
b = 'b'
match a, b:
case 'a', _:
print('a')
The above code causes a break when running pre-commit hooks even though it is syntactically valid:
root@fed07c6390e1:/exos# pre-commit run add-trailing-comma --files mwe.py
Add trailing commas......................................................Failed
hook id: add-trailing-comma
exit code: 1
Traceback (most recent call last):
File "/root/.cache/pre-commit/repo57gmvexh/py_env-python3.10/bin/add-trailing-comma", line 8, in
sys.exit(main())
File "/root/.cache/pre-commit/repo57gmvexh/py_env-python3.10/lib/python3.10/site-packages/add_trailing_comma/_main.py", line 102, in main
ret |= fix_file(filename, args)
File "/root/.cache/pre-commit/repo57gmvexh/py_env-python3.10/lib/python3.10/site-packages/add_trailing_comma/_main.py", line 71, in fix_file
contents_text = _fix_src(contents_text, args.min_version)
File "/root/.cache/pre-commit/repo57gmvexh/py_env-python3.10/lib/python3.10/site-packages/add_trailing_comma/_main.py", line 45, in _fix_src
callback(i, tokens)
File "/root/.cache/pre-commit/repo57gmvexh/py_env-python3.10/lib/python3.10/site-packages/add_trailing_comma/_plugins/match.py", line 57, in _fix_sequence
find_simple(i, tokens),
File "/root/.cache/pre-commit/repo57gmvexh/py_env-python3.10/lib/python3.10/site-packages/add_trailing_comma/_token_helpers.py", line 43, in find_simple
raise AssertionError('Past end?')
AssertionError: Past end?
However if I add parens around the case in the match statement there is no break
a = 'a'
b = 'b'
match a, b:
case ('a', _):
print('a')
root@fed07c6390e1:/exos# pre-commit run add-trailing-comma --files mwe.py
Add trailing commas......................................................Passed
The original example passes for ==2.1.0
but breaks on >=2.2.0
Hi, would it be possible to provide support for Jupyter notebooks?
black
offers a Jupyter pre-commit hook, but its trailing comma strategy is different from this tool's, because it doesn't add trailing commas when there's only one line of arguments:
some_function(
arg1, arg2, arg3
)
$ python -Wonce $(which add-trailing-comma) t.py
<unknown>:1: DeprecationWarning: invalid escape sequence \q
It would be nice to ignore these warnings just like pyupgrade does: https://github.com/asottile/pyupgrade/blob/847d0caf9d57666ce06d58421cec982176e8a256/pyupgrade.py#L66-L70
Hey, I found this while using this as a pre-commit hook (big fan of the the project & your tools btw! :)).
It seems the tool may change turn a type into a tuple[type] in a situation like this;
x = (
object # < comma is added here
), object
I suspect something has changed in offset information in ast. See if it's a fix or a bug and report before 3.8 releases
$ pytest tests -v | grep FAILED
tests/add_trailing_comma_test.py::test_fixes_calls[(\n {k: v},\n ()\n)-(\n {k: v},\n (),\n)] FAILED [ 15%]
tests/add_trailing_comma_test.py::test_fixes_literals[x = (\n 1,\n 2\n)-x = (\n 1,\n 2,\n)] FAILED [ 25%]
tests/add_trailing_comma_test.py::test_fixes_py35_plus_literals[x = (\n 1, *y\n)-x = (\n 1, *y,\n)] FAILED [ 28%]
tests/add_trailing_comma_test.py::test_fix_unhugs[x = (f(\n a,\n), f(\n a,\n))-x = (\n f(\n a,\n ), f(\n a,\n ),\n)] FAILED [ 59%]
tests/add_trailing_comma_test.py::test_fix_unhugs[x = ([a,\n b], None)-x = (\n [\n a,\n b,\n ], None,\n)] FAILED [ 64%]
Seems to be related to tuple offset calculation -- which I'm pretty sure was buggy before
if (foo and
bar()):
pass
I expect to be rewritten to
if (
foo and
bar()
):
pass
But I imagine the same code that prevents this from being rewritten is firing:
foo('bar {}'.format(
'baz',
))
which I don't think should be rewritten.
Need to come up with a more clever heuristic here.
def f(
*args): pass
f(
*args)
def f(
*args
): pass
f(
*args
)
no change
these two types are pruned during the trailing comma determination, but should still apply unhugging
I would expect this to add trailing commas to multiple imports:
from foo import (
bar,
baz,
)
Hi!
I've started using this tool, and the following is happening
ValueError("something ...",)
I'm not sure if that's desired, but I'd like to avoid adding trailing comma here. ( It also happens in print
s statements with a single string) - Currently flake8-commas
1 mark them as trailing comma prohibited (C819)
.
Is there a way to avoid adding trailing comma in specific lines ?
Thanks!
Similar to #22
(
{k: v},
()
)
``
Is not adding a trailing comma after the second tuple
Hey @asottile ; I am trying to use add-trailing-comma
as part of formatting and use flake8-comma
as check against it. I can see this as help:
usage: add-trailing-comma [-h] [--exit-zero-even-if-changed] [--py35-plus] [--py36-plus] [filenames ...]
My understanding is the directory
option is not currently available. I have seen black
or isort
have this ability:
--src SRC_PATHS, --src-path SRC_PATHS
Add an explicitly defined source path (modules within src paths have their imports automatically categorized as first_party). Glob expansion (`*` and `**`) is supported for
this option.
I was wondering maybe this can be a very helpful feature. I also appreciate it if you direct me how can I apply this on a directory. For example, lets say I have src/
and tests/
and I wanna apply add-trailing-comma
to all .py
files.
Currently, I am running the snippet below (I use poetry
) in my formatting
scripts:
poetry run add-trailing-comma src/**/*.py tests/**/*.py
Create a test.py
:
# -*- coding: utf-8 -*-
test = [
1,
2
]
add-trailing-comma - < test.py
outputs correctly:
# -*- coding: utf-8 -*-
test = [
1,
2,
]
But the return statuscode is 1
:
❯ echo $? [11:30:11]
1
This is a different behavior from other formatters, like black:
black - < test.py [11:30:46]
# -*- coding: utf-8 -*-
test = [1, 2]
reformatted -
All done! ✨ 🍰 ✨
1 file reformatted.
❯ echo $? [11:30:54]
0
Some formatters in editors (like vim-autoformat) expect a 0
statuscode to make sure the formatter call was ok, and this is inconsistent with exit codes with special meanings.
Since the stdin
feature comes from a month old PR (#75), I think it's nice to consider changing this to be standard like other tools.
Add support for trailing commas for this:
with (
foo as bar,
- baz as womp
+ baz as womp,
):
# ...
In my organization we are using codestyle with dangling braces:
data = {
'key1': 1,
'key2': 2,
'key3': 3,
}
val = 1
The reasoning behind this style is pretty simple: if there is a char in the first column, then there is a variable declaration, block statement, function call, etc., and everything till next char in the first column belongs to this statement. Such approach is pretty useful, for example, in constants module: quickly scroll file to locate constant of interest just by looking at first column and braces wont mess up view.
In addition to the above, some text editors have different collapsing. For example, in Notepad++:
With indent:
Without indent:
We would like to use add-trailing-comma to automatically add trailing commas as well as other features you implemented except for de-indention of braces. Do you have plans to add options to customize the behavior of the script? And why you decided to add this feature to this package?
For instance:
@foo('bar' baz')
def baz(
foo
):
pass
I expect that to be rewritten as follows:
@foo('bar' baz')
def baz(
- foo
+ foo,
):
pass
f('long'
'literal')
f(
'long'
'literal'
)
f(
'long'
'literal',
)
This should resolve in a single pass
Before add-trailing-comma
def g(dict_representation):
assert (
set(dict_representation["cli"].pop("characteristics")
) == set(cli_data.pop("characteristics"))
)
after add-trailing-comma
def g(dict_representation):
assert (
set(
dict_representation["cli"].pop("characteristics"), # there should not be any comma, because set() gets only one parameter
) == set(cli_data.pop("characteristics"))
)
This code ...
bankrupts = [{
'id': company.bankrupt_id,
'type': 'company',
} for company in found_companies]
... shouldn't be rewritten (IMHO) with:
bankrupts = [
{
'id': company.bankrupt_id,
'type': 'company',
} for company in found_companies
]
And vice versa
They are both valid
Also this similar case already works exactly that way, the tool doesn't touch it:
assert response['error'] == {
'data': {'errors': [
{'code': 'code1', 'message': 'message1'},
{'code': 'code2', 'message': 'message2'},
]},
}
Could documentation about compatibility with isort be added?
Specifically, multi_line_output
must be set to either 2, 7 or 9
(2-hanging, 7-noqa, 9-vertical-prefix-from-module-import)
OR set include_trailing_comma=true
and multi_line_output
to 2, 3, 5, 7 or 9
(2-hanging, 3-vert-hanging, 5-vert-grid-grouped, 7-noqa, 9-vertical-prefix-from-module-import)
(note: technically multi_line_output=2 + include_trailing_comma=true is broken, but that's an isort issue that can be fixed eventually (see: PyCQA/isort#1864), I've also omitted 6 as it is deprecated)
Any other mode will result in missing trailing comma or indentation that conflicts with this tool.
Didn't initially realise that args had to be on separate lines for functions in order for add-trailing-comma
to modify (in original comment). Realised that and added to # edit
.
# requirements.txt
appdirs==1.4.4
cfgv==3.3.0
distlib==0.3.1
filelock==3.0.12
identify==2.2.6
nodeenv==1.6.0
pre-commit==2.13.0
PyYAML==5.4.1
six==1.16.0
toml==0.10.2
virtualenv==20.4.7
#.pre-commit-config.yaml
minimum_pre_commit_version: 2.10.0
repos:
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.1.0
hooks:
- id: add-trailing-comma
args: [--py36-plus]
Running pre-commit
as: pre-commit run --all-files
I'm expecting (hoping...) with the following test file:
def A(*, a):
return True
def B(a,b):
return True
def C(*args):
return True
x = [1, 2, 3]
def function_call(a, b, c):
return True
function_call(
a=1, b=2, c=3
)
Gives the diff:
diff --git a/test.py b/test.py
index 6bc7d22..edf345f 100644
--- a/test.py
+++ b/test.py
@@ -13,5 +13,5 @@ def function_call(a, b, c):
return True
function_call(
- a=1, b=2, c=3
+ a=1, b=2, c=3,
)
Though the diff that I was expecting (...hoping?) for was:
diff --git a/test.py b/test.py
index 6bc7d22..768e441 100644
--- a/test.py
+++ b/test.py
@@ -1,17 +1,17 @@
-def A(*, a):
+def A(*, a,):
return True
-def B(a,b):
+def B(a,b,):
return True
-def C(*args):
+def C(*args,):
return True
-x = [1, 2, 3]
+x = [1, 2, 3,]
-def function_call(a, b, c):
+def function_call(a, b, c,):
return True
function_call(
- a=1, b=2, c=3
+ a=1, b=2, c=3,
)
There's probably something that I'm missing - but having looked through the readme I'm not sure what.
Given the following file:
def A(*,
a):
return True
def B(a,
b):
return True
def C(*args
):
return True
x = [1, 2, 3]
def function_call(a, b,
c):
return True
function_call(
a=1, b=2, c=3
)
the diff is as expected having run : pre-commit run --all-files
:
diff --git a/test.py b/test.py
index f37eb5c..361e427 100644
--- a/test.py
+++ b/test.py
@@ -1,21 +1,28 @@
-def A(*,
-a):
+def A(
+ *,
+ a,
+):
return True
-def B(a,
-b):
+def B(
+ a,
+ b,
+):
return True
-def C(*args
+def C(
+ *args,
):
return True
x = [1, 2, 3]
-def function_call(a, b,
-c):
+def function_call(
+ a, b,
+ c,
+):
return True
function_call(
- a=1, b=2, c=3
+ a=1, b=2, c=3,
)
Seems I didn't realise that they had to be on separate lines in order for add-trailing-comma
to pick up on them.
If there's a way to set this so that add-trailing-comma
added a trailing comma to functions all the time that would be ideal.
If not then this may have shifted from an issue to a feature request and can probably be closed 😄
I came across this bizarre issue:
$ pre-commit run --files tests/plugins/high_entropy_strings_test.py
autopep8 wrapper.........................................................Failed
hookid: autopep8-wrapper
Files were modified by this hook. Additional output:
Fixing tests/plugins/high_entropy_strings_test.py
Add trailing commas......................................................Failed
hookid: add-trailing-comma
Files were modified by this hook. Additional output:
Rewriting tests/plugins/high_entropy_strings_test.py
$
$ git status
On branch master
nothing to commit, working directory clean
Turns out they were cancelling each other out!
$ pre-commit run autopep8-wrapper --files tests/plugins/high_entropy_strings_test.py
autopep8 wrapper.........................................................Failed
hookid: autopep8-wrapper
Files were modified by this hook. Additional output:
Fixing tests/plugins/high_entropy_strings_test.py
$ git diff
diff --git a/tests/plugins/high_entropy_strings_test.py b/tests/plugins/high_entropy_strings_test.py
index 14adbe5..2330435 100644
--- a/tests/plugins/high_entropy_strings_test.py
+++ b/tests/plugins/high_entropy_strings_test.py
@@ -203,8 +203,8 @@ class TestHexHighEntropyStrings(HighEntropyStringsTest):
assert self.logic.calculate_shannon_entropy('0123456789') < \
self.logic.calculate_shannon_entropy(
'01234567890123456789',
- )
+ )
$
$ pre-commit run add-trailing-comma --files tests/plugins/high_entropy_strings_test.py
Add trailing commas......................................................Failed
hookid: add-trailing-comma
Files were modified by this hook. Additional output:
Rewriting tests/plugins/high_entropy_strings_test.py
$ git diff
diff --git a/tests/plugins/high_entropy_strings_test.py b/tests/plugins/high_entropy_strings_test.py
index 2330435..d33429b 100644
--- a/tests/plugins/high_entropy_strings_test.py
+++ b/tests/plugins/high_entropy_strings_test.py
@@ -203,7 +203,7 @@ class TestHexHighEntropyStrings(HighEntropyStringsTest):
assert self.logic.calculate_shannon_entropy('0123456789') < \
self.logic.calculate_shannon_entropy(
'01234567890123456789',
- )
+ )
So I've upgraded Python in jobs where I run linters (and pre-commit in particular) from Python 3.7 to Python 3.8 and it started breaking the generator expressions that are the only args passed into function calls.
I confirmed locally that setting Python 3.7 fixes the behavior and Python 3.8 breaks it.
To give an example, here's a dict construction code that add-trailing-comma
preserves when running under Python 3.7
return dict(
(gw.version, gw)
for gw in cls.__subclasses__()
)
But under Python 3.8, it breaks the syntax like this:
return dict(
(gw.version, gw)
- for gw in cls.__subclasses__()
+ for gw in cls.__subclasses__(),
)
It's not a style complaint. It breaks the AST parser and makes it non-runnable because generator expressions
have to be enclosed with braces. And should one add a comma, implying more args passed to the function, they'd have to wrap the generator expression using an extra pair of parentheses (that can be omitted when there's only one arg and no comma).
Ref: https://github.com/cherrypy/cheroot/runs/890705032#step:9:122
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.