prettier / plugin-python Goto Github PK
View Code? Open in Web Editor NEWPrettier Python Plugin
License: MIT License
Prettier Python Plugin
License: MIT License
hi guys, great work!
i just ran the prettier on one of my projects and i got some bugs,
all of the above happen in python 2.7
1.on slice notation, its not detecting the parenthesis,
for example,
before prettier:
some_var[1:]
after prettier:
some_var[1]
2.on not clause, not token will concatenate to the next token,
before prettier:
if not is_something:
do_something()
after prettier:
if notis_something:
do_something()
3.function signature with default values and splitted to few lines doesnt work well:
before prettier:
def init(self, db_mail_info=None,
email_sent_time=None):
after prettier:
def init(self, db_mail_info, email_sent_time=None, ):
4. mixed and or statement removes parenthesis so the logic is changing:
before prettier:
if x and (y or z):
do_something()
after prettier:
if x and y or z:
do_something()
thanks!
There is no description.
This:
def i18n_patterns(*urls, prefix_default_language=True):
pass
gets changed to:
def i18n_patterns(*urls, *, prefix_default_language=True):
pass
This plugin stuff looks great!
I don't have a concrete proposal here, yet, but I'd like to raise a point about how integration should look. As a Python user, ideally I'd like my workflow to look something like:
$ brew install prettier
$ pip install prettier # Or maybe prettier-python.
Why? Well, it's nice not to have to reach out to npm when I'm working with Python. Additionally, while the vendoring here certainly works, it's not quite ideal (you'd have to tweak PYTHONPATH
to scale things up).
It shouldn't be difficult to pull in the doc builders from Prettier and write them in Python, for example, which then ought to open up implementing all of this in Python.
The question, then, would be how to actually register the plugin.
(FYI) To align with the npm names I have renamed all the official plugins to prettier/plugin-*
.
I get this error why trying to run prettier
on SmokeDetector:
$ npx prettier chatcommunicate.py --write
[error] chatcommunicate.py: Error: Traceback (most recent call last):
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 123, in <module>
[error] main()
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 118, in main
[error] json = export_json(tree, True)
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 10, in export_json
[error] dict = export_dict(atok)
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 26, in export_dict
[error] return DictExportVisitor(atok).visit(atok.tree)
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 38, in visit
[error] return meth(node)
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 53, in default_visit
[error] args[field] = meth(getattr(node, field))
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 76, in default_visit_field
[error] return [self.visit(x) for x in val]
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 76, in <listcomp>
[error] return [self.visit(x) for x in val]
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 38, in visit
[error] return meth(node)
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 53, in default_visit
[error] args[field] = meth(getattr(node, field))
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 76, in default_visit_field
[error] return [self.visit(x) for x in val]
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 76, in <listcomp>
[error] return [self.visit(x) for x in val]
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 38, in visit
[error] return meth(node)
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 53, in default_visit
[error] args[field] = meth(getattr(node, field))
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 76, in default_visit_field
[error] return [self.visit(x) for x in val]
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 76, in <listcomp>
[error] return [self.visit(x) for x in val]
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 38, in visit
[error] return meth(node)
[error] File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 47, in default_visit
[error] for field in node._fields:
[error] AttributeError: 'str' object has no attribute '_fields'
[error]
[error] at parseText (.../SmokeDetector/node_modules/@prettier/plugin-python/src/parser.js:18:11)
[error] at Object.parse (.../SmokeDetector/node_modules/@prettier/plugin-python/src/parser.js:26:27)
[error] at Object.parse$4 [as parse] (.../SmokeDetector/node_modules/prettier/bin-prettier.js:23176:19)
[error] at formatWithCursor (.../SmokeDetector/node_modules/prettier/bin-prettier.js:32534:27)
[error] at Object.formatWithCursor (.../SmokeDetector/node_modules/prettier/bin-prettier.js:32835:12)
[error] at format$1 (.../SmokeDetector/node_modules/prettier/bin-prettier.js:38985:21)
[error] at eachFilename (.../SmokeDetector/node_modules/prettier/bin-prettier.js:39208:16)
[error] at filePaths.forEach.filePath (.../SmokeDetector/node_modules/prettier/bin-prettier.js:39150:7)
[error] at Array.forEach (<anonymous>)
[error] at eachFilename (.../SmokeDetector/node_modules/prettier/bin-prettier.js:39149:15)
[error] at Object.formatFiles (.../SmokeDetector/node_modules/prettier/bin-prettier.js:39166:3)
[error] at Object.run (.../SmokeDetector/node_modules/prettier/bin-prettier.js:39789:14)
[error] at Object.<anonymous> (.../SmokeDetector/node_modules/prettier/bin-prettier.js:39804:5)
[error] at Module._compile (module.js:660:30)
[error] at Object.Module._extensions..js (module.js:671:10)
[error] at Module.load (module.js:573:32)
[error] at tryModuleLoad (module.js:513:12)
[error] at Function.Module._load (module.js:505:3)
[error] at Function.Module.runMain (module.js:701:10)
[error] at findNodeScript.then.existing (/Users/hayfields/.nvm/versions/node/v9.4.0/lib/node_modules/npm/node_modules/libnpx/index.js:268:14)
[error] at <anonymous>
It looks like the AST exporter is trying to read the names
field of an ast.Global
object, which contains ['_clients']
in this file.
A Global
node represents a global foo
statement. As a JS object, it looks something like this:
({
names: ['foo']
})
Note that the names are not identifiers.
I did a test run of this on the SmokeDetector codebase, and found a few nodes that aren’t yet supported:
GeneratorExp
: el for el in an_iterable
Set
: { "foo", "bar", "baz" }
YieldFrom
: yield from asyncio.sleep(interval)
Also, I got this error when running Prettier on test/test_chatcommunicate.py
:
Traceback (most recent call last):
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 122, in <module>
main()
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 117, in main
json = export_json(tree, True)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 9, in export_json
dict = export_dict(atok)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 25, in export_dict
return DictExportVisitor(atok).visit(atok.tree)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 37, in visit
return meth(node)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 52, in default_visit
args[field] = meth(getattr(node, field))
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in default_visit_field
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in <listcomp>
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 37, in visit
return meth(node)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 52, in default_visit
args[field] = meth(getattr(node, field))
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in default_visit_field
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in <listcomp>
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 37, in visit
return meth(node)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 52, in default_visit
args[field] = meth(getattr(node, field))
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in default_visit_field
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in <listcomp>
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 37, in visit
return meth(node)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 52, in default_visit
args[field] = meth(getattr(node, field))
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in default_visit_field
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 75, in <listcomp>
return [self.visit(x) for x in val]
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 37, in visit
return meth(node)
File ".../SmokeDetector/node_modules/@prettier/plugin-python/vendor/python/astexport.py", line 46, in default_visit
for field in node._fields:
AttributeError: str object has no attribute _fields
at parseText (.../SmokeDetector/node_modules/@prettier/plugin-python/src/parser.js:18:11)
at Object.parse (.../SmokeDetector/node_modules/@prettier/plugin-python/src/parser.js:26:27)
at Object.parse$4 [as parse] (.../SmokeDetector/node_modules/prettier/index.js:24274:19)
at formatWithCursor (.../SmokeDetector/node_modules/prettier/index.js:33650:27)
at format (.../SmokeDetector/node_modules/prettier/index.js:33695:10)
at Object.format (.../SmokeDetector/node_modules/prettier/index.js:33945:12)
at Object.diagnose (.../SmokeDetector/node_modules/prettylint/lib/diagnose.js:14:30)
at Object.<anonymous> (.../SmokeDetector/node_modules/prettylint/lib/lint.js:33:37)
at step (.../SmokeDetector/node_modules/tslib/tslib.js:133:27)
at Object.next (.../SmokeDetector/node_modules/tslib/tslib.js:114:57)
at fulfilled (.../SmokeDetector/node_modules/tslib/tslib.js:104:62)
at <anonymous> prettier/prettier
Input
l = [i for j in k if j%2 == 0 if j*2 < 20 for i in j if i%2==0]
Output
l = [i for j in k if j % 2 == 0 j * 2 < 20 for i in j if i % 2 == 0]
Expected
l = [i for j in k if j % 2 == 0 if j * 2 < 20 for i in j if i % 2 == 0]
# ^^
I'm not sure if that's even valid code, but it caused AST_COMPARE to fail on python_expressions/expressions.py
.
Minimal repro (I think):
def func():
if condition:
pass
else:
assert something
another_statement()
test.py: TypeError: Cannot read property 'length' of undefined
at FastPath.map (.../node_modules/prettier/src/common/fast-path.js:119:34)
at printBody (.../node_modules/prettier-python/src/printer/index.js:119:50)
at printIf (.../node_modules/prettier-python/src/printer/index.js:154:30)
at parts.push.path.map.p (.../node_modules/prettier-python/src/printer/index.js:167:30)
at FastPath.map (.../node_modules/prettier/src/common/fast-path.js:124:19)
at printIf (.../node_modules/prettier-python/src/printer/index.js:167:21)
at Object.genericPrint [as print] (.../node_modules/prettier-python/src/printer/index.js:453:14)
at genericPrint (.../node_modules/prettier/src/main/ast-to-doc.js:97:18)
at comments.printComments.p (.../node_modules/prettier/src/main/ast-to-doc.js:39:14)
at Object.printComments (.../node_modules/prettier/src/main/comments.js:1102:19)
at printGenerically (.../node_modules/prettier/src/main/ast-to-doc.js:37:22)
at FastPath.map (.../node_modules/prettier/src/common/fast-path.js:124:19)
at printBody (.../node_modules/prettier-python/src/printer/index.js:119:50)
at Object.genericPrint [as print] (.../node_modules/prettier-python/src/printer/index.js:225:34)
at genericPrint .../node_modules/node_modules/prettier/src/main/ast-to-doc.js:97:18)
at comments.printComments.p (.../node_modules/prettier/src/main/ast-to-doc.js:39:14)
at Object.printComments (.../node_modules/prettier/src/main/comments.js:1102:19)
at printGenerically (.../node_modules/prettier/src/main/ast-to-doc.js:37:22)
at FastPath.map (.../node_modules/prettier/src/common/fast-path.js:124:19)
at printBody (.../node_modules/prettier-python/src/printer/index.js:119:50)
at Object.genericPrint [as print] (.../node_modules/prettier-python/src/printer/index.js:191:22)
at genericPrint .../node_modules/prettier/src/main/ast-to-doc.js:97:18)
https://pypi.python.org/pypi/astor
Wanted to let people know I'm working on this. Don't have anything ready to PR yet.
The ideal is that if this integration is possible, then it saves having to write a finicky AST printer for Python, when there already is one.
Ultimately it'd be nice to use standard Python package management instead of vendoring dependencies (for now – since the Python code here has to run in-virtualenv), but that's a longer-term concern that's really more a function of #2.
PEP 8 specifies a max line width of 79: https://www.python.org/dev/peps/pep-0008/#maximum-line-length
People can and do override this, but it would be nice if the no-config default for Python were 79 instead of 80, somehow.
They should only have one
EDIT: they should actually be empty, example here: https://github.com/django/django/blob/master/tests/str/__init__.py
When I try to use it with following configuration, it throws
TypeError: Cannot read property 'toString' of null
prettier.format("print('Hello, world!')", {
parser: 'python',
plugins: ['@prettier/plugin-python'],
});
In:
a = 1,
Out:
a = 1
The trailing comma is necessary for single-element tuples in Python, with out without the parens (i.e. (1,)
, not (1)
).
this is hand-tuned, yapf/pep8 don't really care about any of that (they pass-through, it seems):
def fetch(content, prefix):
return {
'parts': pipe(parse('$..layers').find(content), mapcat(lambda m: m.value),
filter(lambda v: v['exportOptions']['exportFormats']),
filter(lambda v: re.match(prefix, v['name'])),
map(lambda v: glom(v, {'key': 'name',
'layout': ('frame', {'left': ('x', round),
'top': ('y', round),
'width': ('width', round),
'height': ('height', round)}) })),
sorted(key=lambda p: p['key']),
list)
}
with prettier
def fetch(content, prefix):
return \
{
"parts":
pipe(parse("$..layers").find(content), mapcat(lambda m: \
m.value), filter(lambda v: \
v["exportOptions"]["exportFormats"]), filter(lambda \
v \
: \
re.match(prefix, v["name"])), map(lambda v: \
glom(v, {
"key": "name",
"layout":
(
"frame",
{
"left": ("x", round),
"top": ("y", round),
"width": ("width", round),
"height": ("height", round)
}
)
})), sorted(key=lambda p: p["key"]), list)
}
Running prettier on a python file with just comments errors because the last comment doesn't get printed.
Example file:
# 1
# 2
Here's the error:
yarn run v1.2.1
$ prettier --plugin=. --parser=python tests/python_comments/just_comments.py
[error] tests/python_comments/comments.py: Error: Comment "# 2" was not printed. Please report this error!
[error] at astComments.forEach.comment (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/index.js:61:13)
[error] at Array.forEach (<anonymous>)
[error] at ensureAllCommentsPrinted (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/index.js:59:15)
[error] at formatWithCursor (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/index.js:129:3)
[error] at Object.formatWithCursor (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/index.js:402:12)
[error] at format (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/src/cli/util.js:157:19)
[error] at eachFilename (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/src/cli/util.js:380:16)
[error] at filePaths.forEach.filePath (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/src/cli/util.js:322:7)
[error] at Array.forEach (<anonymous>)
[error] at eachFilename (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/src/cli/util.js:321:15)
[error] at Object.formatFiles (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/src/cli/util.js:338:3)
[error] at Object.run (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/src/cli/index.js:60:12)
[error] at Object.<anonymous> (/Users/ryanashcraft/Projects/plugin-python/node_modules/prettier/bin/prettier.js:5:23)
[error] at Module._compile (module.js:624:30)
[error] at Object.Module._extensions..js (module.js:635:10)
[error] at Module.load (module.js:545:32)
error Command failed with exit code 2.
I can repro the same issue for JavaScript by removing these lines from printer-estree.js
.
Conversely, I can hack a fix for python by importing the comments
module from prettier/src/main/comments.js
and concating to the return value of comments.printDanglingComments(path, options, /* sameIndent */ true)
to the "Module" AST type return value.
Not sure what it would take to fix this properly.
I think, that we must use MIT licence. Same as https://github.com/prettier/prettier
@patrick91 without licence some projects cannot use this tool.
Found this issue in my codebase.
Input:
deck, created = Deck.objects.get_or_create_from_id_list(
decklist,
hero_id=player._hero.card_id,
game_type=game_type,
classify_archetype=True
)
Output:
(
deck,
created,
) = Deck.objects.get_or_create_from_id_list(decklist, hero_id=player._hero.card_id, game_type=game_type, classify_archetype=True)
This is wrong on two accounts: The multi-assignment should never be assigned to a tuple like that (even though it's syntactically correct, nobody does that). And the arguments to the method called on top of that shouldn't be rewrapped into a single line as that line ends up being too long. (Default params except tab, so 80 line length)
I had started a small repo with a python test suite here: https://github.com/patrick91/prettier-python-tests
Now that we have a separate repo we could add these tests here, instead of having a separate repo.
- main(sys.argv[1:])
+ main(sys.argv[1])
this:
raise NotImplementedError(
'The SimpleListFilter.lookups() method must be overridden to '
'return a list of tuples (value, verbose value).'
)
gets converted to
raise
NotImplementedError('The SimpleListFilter.lookups() method must be overridden to '
'return a list of tuples (value, verbose value).'
)
Seeing:
[error] src/bkyml/__init__.py: SyntaxError: Unexpected character '#' (1:1)
[error] > 1 | # -*- coding: utf-8 -*-
[error] | ^
[error] 2 | from pkg_resources import get_distribution, DistributionNotFound
[error] 3 |
for
# -*- coding: utf-8 -*-
from pkg_resources import get_distribution, DistributionNotFound
try:
# Change here if project is renamed and does not equal the package name
dist_name = __name__
__version__ = get_distribution(dist_name).version
except DistributionNotFound:
__version__ = 'unknown'
generated via https://pyscaffold.org/
Ran via: yarn prettier -- --write "src/**/*.py"
Stack trace:
[error] ../../tmp/pinecast/accounts/migrations/0001_initial.py: Error: Traceback (most recent call last):
[error] File "/opt/prettier-python/vendor/python/astexport.py", line 123, in <module>
[error] main()
[error] File "/opt/prettier-python/vendor/python/astexport.py", line 118, in main
[error] json = export_json(tree, True)
[error] File "/opt/prettier-python/vendor/python/astexport.py", line 21, in export_json
[error] separators=(",", ": ") if pretty_print else (",", ":")
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 238, in dumps
[error] **kw).encode(obj)
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 201, in encode
[error] chunks = list(chunks)
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 430, in _iterencode
[error] yield from _iterencode_dict(o, _current_indent_level)
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
[error] yield from chunks
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 437, in _iterencode
[error] o = _default(o)
[error] File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default
[error] o.__class__.__name__)
[error] TypeError: Object of type 'bytes' is not JSON serializable
[error]
[error] at parseText (/opt/prettier-python/src/parser.js:18:11)
[error] at Object.parse (/opt/prettier-python/src/parser.js:26:27)
[error] at Object.parse (/opt/prettier-python/node_modules/prettier/src/main/parser.js:75:19)
[error] at formatWithCursor (/opt/prettier-python/node_modules/prettier/index.js:101:25)
[error] at Object.formatWithCursor (/opt/prettier-python/node_modules/prettier/index.js:402:12)
[error] at format (/opt/prettier-python/node_modules/prettier/src/cli/util.js:157:19)
[error] at eachFilename (/opt/prettier-python/node_modules/prettier/src/cli/util.js:380:16)
[error] at filePaths.forEach.filePath (/opt/prettier-python/node_modules/prettier/src/cli/util.js:322:7)
[error] at Array.forEach (<anonymous>)
[error] at eachFilename (/opt/prettier-python/node_modules/prettier/src/cli/util.js:321:15)
[error] at Object.formatFiles (/opt/prettier-python/node_modules/prettier/src/cli/util.js:338:3)
[error] at Object.run (/opt/prettier-python/node_modules/prettier/src/cli/index.js:60:12)
[error] at Object.<anonymous> (/opt/prettier-python/node_modules/prettier/bin/prettier.js:5:23)
[error] at Module._compile (module.js:660:30)
[error] at Object.Module._extensions..js (module.js:671:10)
[error] at Module.load (module.js:573:32)
While parsing this file:
https://github.com/Pinecast/pinecast/blob/master/accounts/migrations/0001_initial.py
Running Python 3.6.4
del list_item[4]
del dictionary["alpha"]
Currently the test suite covers several python3 language features that did not exist pre-3.6. So running yarn test
on a system with python 3.4, for example, you get several tests failing from parse errors. Perhaps we should add an explicit version check before parsing and log a warning or throw an error? plugin-swift does this: https://github.com/prettier/plugin-swift/blob/master/src/parser/wrapper.js.
plugin-python/vendor/python/six.py
Line 831 in 04dc40a
The def with_metaclass()
implementation assumes that all meta classes have __prepare__
defined.
The Python Reference says (https://docs.python.org/3/reference/datamodel.html#preparing-the-class-namespace):
If the metaclass has a
__prepare__
attribute, it is called as [...].If the metaclass has no
__prepare__
attribute, then the class namespace is initialised as an empty ordered mapping.
Therefore, I think six
should check existence of __prepare__
attribute before calling it, as __prepare__
is not defined on type
in PY2.
PEP 448 dictionary spreading creates invalid syntax
x = {}
merged = {**x}
becomes
x = {}
merged = {: x}
using git master version of plugin:
git+https://github.com/prettier/plugin-python.git#036c8a66c166ed710b2a0d280e4c85015a1a34c5
("version": "0.0.0-development"
)
Just FYI @patrick91, I've added you to the prettier
org on npm and the python
team therein, so you should now have publish rights to the @prettier/plugin-python
package.
Let me know if you want me to add anyone else.
This:
combination = {**first_dictionary, "x": 1, "y": 2}
gets changed to:
combination = {: first_dictionary, "x": 1, "y": 2}
See: #49 (comment)
There are a number of cases in Python where the token-to-AST mapping is very clearly non-injective, where multiple different-looking statements are syntactically equivalent. We should think about how to handle these; perhaps this will require looking at the actual tokens.
Usually only one use case is common, but mangling tokens might be a bit much.
elif
(#7)if foo:
foo()
elif bar:
bar()
if foo:
foo()
else:
if bar:
bar()
with
in Python 2 (#15)with a, b:
pass
with a:
with b:
pass
as
in except
in Python 2try:
foo()
except A as a:
pass
try:
foo()
except A, a:
pass
class Foo:
pass
class Foo():
pass
my_func_with_many_args(0, *args, var_e=5, var_j=6, **kwargs)
Becomes:
my_func_with_many_args(*args, **kwargs, 0, var_e=5, var_j=6)
Input:
TEMPLATES = [{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
"/some/path/to/some/example/directory",
],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
}]
Output:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": ["/some/path/to/some/example/directory"],
"APP_DIRS": True,
"OPTIONS":
{
"context_processors":
[
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
I don't know anyone who formats dict values like this and it feels very unnatural.
I think it would be a good idea to have some simple instructions on how can someone test the Python integration on their own projects in the current state. Obviously it's not final on how it will work in the end, but since it's under construction anyway it will be much easier for new comers to test it with instructions.
If my code is slicing a list and not specifying start or end, prettier will remove the open-ended side, i.e. the hanging colon. This results in code that executes differently (or sometimes a syntax error).
$ echo "print(test[1:])" > bug_demo.py
$ prettier bug_demo.py
print(test[1])
$ echo "print(test[:])" > bug_demo.py
$ prettier bug_demo.py
print(test[])
The bug doesn't happen when both start and end are given for the slice range.
$ echo "print(test[1:3])" > bug_demo.py
$ prettier bug_demo.py
print(test[1:3])
I noticed this plugin is stripping type hints. Where is supporting type hints in your roadmap?
I've been trying running prettier on the django codebase and I noticed that they use single quotes for almost all the strings and double quotes for the docstrings, which seems to be a common things in python (I haven't seen many single quotes docstrings).
Could shell out to run https://pypi.python.org/pypi/pep8 on the stdin stream?
The whitespace handling in PEP 8 is a little different. Two cases stand out to me as unhandled.
Current:
foo() # This is a comment.
Desired:
bar() # This is a comment.
Current:
def foo():
pass
def bar():
pass
Desired:
def foo():
pass
def bar():
pass
I tried running prettier on some of my code and ran into a crash.
Minimal repro code:
message = (
"hello {}" # comment
).format("world")
Stacktrace:
[error] test.py: Error: Comment location overlaps with node location
[error] at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:119:11)
[error] at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:94:7)
[error] at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:94:7)
[error] at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:94:7)
[error] at comments.forEach (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:168:5)
[error] at Array.forEach (<anonymous>)
[error] at Object.attach (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:160:12)
[error] at attachComments (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/index.js:34:14)
[error] at formatWithCursor (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/index.js:120:23)
[error] at Object.formatWithCursor (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/index.js:402:12)
[error] at format (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:157:19)
[error] at eachFilename (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:380:16)
[error] at filePaths.forEach.filePath (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:322:7)
[error] at Array.forEach (<anonymous>)
[error] at eachFilename (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:321:15)
[error] at Object.formatFiles (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:338:3)
error Command failed with exit code 2.
The same construct in JS works fine:
IN:
var message = (
"hello {}" // comment
).format("world")
OUT:
var message = "hello {}" // comment
.format("world");
I have no experience with the prettier codebase but I'm interested in trying to fix this. I think something is missing from the AST, I printed both JS and Python to try to spot the difference:
{
"type": "File",
"start": 0,
"end": 61,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 0
}
},
"program": {
"type": "Program",
"start": 0,
"end": 61,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 0
}
},
"sourceType": "module",
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 60,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 17
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 60,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 3,
"column": 17
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "message"
},
"name": "message"
},
"init": {
"type": "CallExpression",
"start": 14,
"end": 60,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 3,
"column": 17
}
},
"callee": {
"type": "MemberExpression",
"start": 14,
"end": 51,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 3,
"column": 8
}
},
"object": {
"type": "StringLiteral",
"start": 20,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 14
}
},
"extra": {
"rawValue": "hello {}",
"raw": "\"hello {}\"",
"parenthesized": true,
"parenStart": 14
},
"value": "hello {}",
"leadingComments": null,
"trailingComments": [
{
"type": "CommentLine",
"value": " comment",
"start": 32,
"end": 42,
"loc": {
"start": {
"line": 2,
"column": 16
},
"end": {
"line": 2,
"column": 26
}
}
}
]
},
"property": {
"type": "Identifier",
"start": 45,
"end": 51,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 8
},
"identifierName": "format"
},
"name": "format",
"leadingComments": [
{
"type": "CommentLine",
"value": " comment",
"start": 32,
"end": 42,
"loc": {
"start": {
"line": 2,
"column": 16
},
"end": {
"line": 2,
"column": 26
}
}
}
]
},
"computed": false
},
"arguments": [
{
"type": "StringLiteral",
"start": 52,
"end": 59,
"loc": {
"start": {
"line": 3,
"column": 9
},
"end": {
"line": 3,
"column": 16
}
},
"extra": {
"rawValue": "world",
"raw": "\"world\""
},
"value": "world"
}
]
}
}
],
"kind": "var"
}
],
"directives": []
},
"comments": [
{
"type": "CommentLine",
"value": " comment",
"start": 32,
"end": 42,
"loc": {
"start": {
"line": 2,
"column": 16
},
"end": {
"line": 2,
"column": 26
}
}
}
]
}
{
"ast_type": "Module",
"body": [
{
"ast_type": "Assign",
"col_offset": 0,
"end": 55,
"lineno": 1,
"source": "message = (\n \"hello {}\" # comment\n).format(\"world\")",
"start": 0,
"targets": [
{
"ast_type": "Name",
"col_offset": 0,
"ctx": {
"ast_type": "Store",
"source": ""
},
"end": 7,
"id": "message",
"lineno": 1,
"source": "message",
"start": 0
}
],
"value": {
"args": [
{
"ast_type": "Str",
"col_offset": 9,
"end": 54,
"lineno": 3,
"s": "world",
"source": "\"world\"",
"start": 47
}
],
"ast_type": "Call",
"col_offset": 4,
"end": 55,
"func": {
"ast_type": "Attribute",
"attr": "format",
"col_offset": 4,
"ctx": {
"ast_type": "Load",
"source": ""
},
"end": 46,
"lineno": 2,
"source": "(\n \"hello {}\" # comment\n).format",
"start": 10,
"value": {
"ast_type": "Str",
"col_offset": 4,
"end": 26,
"lineno": 2,
"s": "hello {}",
"source": "\"hello {}\"",
"start": 16
}
},
"keywords": [],
"lineno": 2,
"source": "(\n \"hello {}\" # comment\n).format(\"world\")",
"start": 10
}
}
],
"comments": [
{
"ast_type": "comment",
"end": 37,
"start": 28,
"value": "# comment"
}
],
"end": 55,
"source": "message = (\n \"hello {}\" # comment\n).format(\"world\")",
"start": 0
}
Any pointers on where to start digging to get this fixed?
I tried playing with this but got the following stack trace. Reduced repro steps below:
$ mkdir pr; cd pr
$ yarn add --dev --exact prettier @prettier/plugin-python
$ echo '#!/usr/bin/env python' > foo.py
$ yarn run prettier --write foo.py
yarn run v1.5.1
warning package.json: No license field
$ /home/adys/pr/node_modules/.bin/prettier --write foo.py
foo.py
[error] foo.py: TypeError: locStart is not a function
[error] at comments.forEach (/home/adys/pr/node_modules/prettier/bin-prettier.js:8108:33)
[error] at Array.forEach (<anonymous>)
[error] at Object.attach (/home/adys/pr/node_modules/prettier/bin-prettier.js:8094:12)
[error] at attachComments (/home/adys/pr/node_modules/prettier/bin-prettier.js:32467:14)
[error] at formatWithCursor (/home/adys/pr/node_modules/prettier/bin-prettier.js:32553:23)
[error] at Object.formatWithCursor (/home/adys/pr/node_modules/prettier/bin-prettier.js:32835:12)
[error] at format$1 (/home/adys/pr/node_modules/prettier/bin-prettier.js:38985:21)
[error] at eachFilename (/home/adys/pr/node_modules/prettier/bin-prettier.js:39208:16)
[error] at filePaths.forEach.filePath (/home/adys/pr/node_modules/prettier/bin-prettier.js:39150:7)
[error] at Array.forEach (<anonymous>)
[error] at eachFilename (/home/adys/pr/node_modules/prettier/bin-prettier.js:39149:15)
[error] at Object.formatFiles (/home/adys/pr/node_modules/prettier/bin-prettier.js:39166:3)
[error] at Object.run (/home/adys/pr/node_modules/prettier/bin-prettier.js:39789:14)
[error] at Object.<anonymous> (/home/adys/pr/node_modules/prettier/bin-prettier.js:39804:5)
[error] at Module._compile (module.js:649:30)
[error] at Object.Module._extensions..js (module.js:660:10)
[error] at Module.load (module.js:561:32)
[error] at tryModuleLoad (module.js:501:12)
[error] at Function.Module._load (module.js:493:3)
[error] at Function.Module.runMain (module.js:690:10)
[error] at startup (bootstrap_node.js:194:16)
[error] at bootstrap_node.js:666:3
error An unexpected error occurred: "Command failed.
Exit code: 2
Command: sh
Arguments: -c /home/adys/pr/node_modules/.bin/prettier --write foo.py
Directory: /home/adys/pr
Output:
".
info If you think this is a bug, please open a bug report with the information provided in "/home/adys/pr/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Should be ~
.
Hi, if I try to prettier this code I get the error in the title.
https://github.com/mariusmotea/diyHue/blob/master/BridgeEmulator/HueEmulator3.py
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.