wemake-python-styleguide icon indicating copy to clipboard operation
wemake-python-styleguide copied to clipboard

Forbid tuples without parenthesis

Open dreamflasher opened this issue 3 years ago • 5 comments

Rule request

Thesis

# bad
a = 1, 2

# good
a = (1, 2)

Reasoning

It shocked me to learn that in Python tuples are defined by commas and not parenthesis. This rule request will find a very likely bug that is a = 1,, a one element tuple. Also it improves readability.

dreamflasher avatar Jan 10 '22 18:01 dreamflasher

Good one! But, this is hard to do right now. Due to how AST works.

sobolevn avatar Jan 10 '22 19:01 sobolevn

Good one! But, this is hard to do right now. Due to how AST works.

Interesting! Could you elaborate?

dreamflasher avatar Jan 10 '22 19:01 dreamflasher

The AST is identical for these two cases:

>>> import ast
>>> code1 = 'a = (1, 2)'
>>> code2 = 'a = 1, 2'
>>> for node in ast.walk(ast.parse(code1)):
...    print(ast.dump(node))
... 
Module(body=[Assign(targets=[Name(id='a', ctx=Store())], value=Tuple(elts=[Constant(value=1), Constant(value=2)], ctx=Load()))], type_ignores=[])
Assign(targets=[Name(id='a', ctx=Store())], value=Tuple(elts=[Constant(value=1), Constant(value=2)], ctx=Load()))
Name(id='a', ctx=Store())
Tuple(elts=[Constant(value=1), Constant(value=2)], ctx=Load())
Store()
Constant(value=1)
Constant(value=2)
Load()

>>> for node in ast.walk(ast.parse(code2)):
...    print(ast.dump(node))
... 
Module(body=[Assign(targets=[Name(id='a', ctx=Store())], value=Tuple(elts=[Constant(value=1), Constant(value=2)], ctx=Load()))], type_ignores=[])
Assign(targets=[Name(id='a', ctx=Store())], value=Tuple(elts=[Constant(value=1), Constant(value=2)], ctx=Load()))
Name(id='a', ctx=Store())
Tuple(elts=[Constant(value=1), Constant(value=2)], ctx=Load())
Store()
Constant(value=1)
Constant(value=2)
Load()

So you either need:

  • CST (unstable)
  • Token-based solution (really hard to do)

sobolevn avatar Jan 10 '22 19:01 sobolevn

Thank you! There is https://pypi.org/project/flake8-tuple/

dreamflasher avatar Jan 11 '22 06:01 dreamflasher

Yes, it is using tokens: https://github.com/ar4s/flake8_tuple/blob/3d706b0f4ae6a7dda516677031af86a2b72b19c8/flake8_tuple.py#L102-L124

sobolevn avatar Jan 11 '22 08:01 sobolevn