wemake-python-styleguide
wemake-python-styleguide copied to clipboard
Forbid tuples without parenthesis
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.
Good one! But, this is hard to do right now. Due to how AST works.
Good one! But, this is hard to do right now. Due to how AST works.
Interesting! Could you elaborate?
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)
Thank you! There is https://pypi.org/project/flake8-tuple/
Yes, it is using tokens: https://github.com/ar4s/flake8_tuple/blob/3d706b0f4ae6a7dda516677031af86a2b72b19c8/flake8_tuple.py#L102-L124