Code Monkey home page Code Monkey logo

plugin-python's Introduction

Prettier Banner

Opinionated Code Formatter

JavaScript · TypeScript · Flow · JSX · JSON
CSS · SCSS · Less
HTML · Vue · Angular
GraphQL · Markdown · YAML
Your favorite language?

Github Actions Build Status Github Actions Build Status Github Actions Build Status Codecov Coverage Status Blazing Fast
npm version weekly downloads from npm code style: prettier Follow Prettier on Twitter

Intro

Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.

Input

foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne());

Output

foo(
  reallyLongArg(),
  omgSoManyParameters(),
  IShouldRefactorThis(),
  isThereSeriouslyAnotherOne(),
);

Prettier can be run in your editor on-save, in a pre-commit hook, or in CI environments to ensure your codebase has a consistent style without devs ever having to post a nit-picky comment on a code review ever again!


Documentation

Install · Options · CLI · API

Playground


Badge

Show the world you're using Prettiercode style: prettier

[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)

Contributing

See CONTRIBUTING.md.

plugin-python's People

Contributors

azz avatar expobrain avatar fuegofro avatar j-f1 avatar kazhuravlev avatar paradoxxxzero avatar patrick91 avatar ryanashcraft avatar taion avatar vjeux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plugin-python's Issues

`global foo` crashes the AST serializer

I get this error why trying to run prettier on SmokeDetector:

Long stack trace; click to show
$ 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.

tokenizing errors

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!

Nested list comprehension printed invalid

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.

Try using astor for AST printing

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.

Parser crash when parsing byte string literals?

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

PEP 8 whitespace handling

The whitespace handling in PEP 8 is a little different. Two cases stand out to me as unhandled.

Two spaces before inline comments

Current:

foo() # This is a comment.

Desired:

bar()  # This is a comment.

Two newlines between functions and classes at indent level 0

Current:

def foo():
    pass

def bar():
    pass

Desired:

def foo():
    pass


def bar():
    pass

How to use it with prettier API?

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'],
});

Render docstrings with double quotes

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).

Multi-variable assignment is split over multiple lines

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)

How would you expect this to be formatted?

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)
        }

Fatal error with comment-only file

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.

Unsupported node types

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

Unnatural formatting of dict/list dict values

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.

Simple instructions on README on how to test this while under construction

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.

Comment directives (# -*- coding: utf-8 -*-) throw

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"

Crash with inline comment in assign expression

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:

JS AST

{
  "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
        }
      }
    }
  ]
}

Python AST

{
  "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?

Integration model for Prettier + Python

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 - package access granted

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.

TypeError: locStart is not a function

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.

yarn-error.log

issue with python3 dictionary unpacking

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")

Wrong wrap of raise expressions when line is too long

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).'
)

Open-ended slice notation gets removed

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])

Support for mypy types?

I noticed this plugin is stripping type hints. Where is supporting type hints in your roadmap?

with_metaclass: check existence of `__prepare__` attribute before calling it

return meta.__prepare__(name, bases)

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.

Non-injective token to AST mappings

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.

1. elif (#7)

if foo:
    foo()
elif bar:
    bar()


if foo:
    foo()
else:
    if bar:
        bar()

2. Nested with in Python 2 (#15)

with a, b:
    pass


with a:
    with b:
        pass

3. as in except in Python 2

try:
    foo()
except A as a:
    pass


try:
    foo()
except A, a:
    pass

4. Empty parent class

class Foo:
    pass


class Foo():
    pass

Crash on assert inside `if` statement

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.