MartinThoma / flake8-simplify

❄ A flake8 plugin that helps you to simplify code
MIT License
185 stars 19 forks source link

[New Rule] Replace f-string without any text with using value directly instead #71

Open simon-liebehenschel opened 2 years ago

simon-liebehenschel commented 2 years ago

Explanation

Analyze f-strings. If f-string has no text and only a passed value, then use that value directly.

Example 1

# Bad

foo = "bar"
my_text = f"{foo}"
# Good

foo = "bar"
my_text = foo

Example 2

# Bad

def my_func(foo: str):
    my_text = f"{foo}"
# Good
def my_func(foo: str):
    my_text = foo

Example 3

# Bad

my_number = 123
my_text = f"{foo}"
# Good

my_number = 123
my_text = str(foo)
simon-liebehenschel commented 2 years ago

Could you please let me know whether your plugin can detect types or I need to address this feature implementation to Mypy?

rpdelaney commented 2 years ago

I just came here to request this exact feature!

Could you please let me know whether your plugin can detect types or I need to address this feature implementation to Mypy?

Maybe I misunderstand. Why would simplify need to perform type checking to know that this pattern is incorrect?

simon-liebehenschel commented 2 years ago

Maybe I misunderstand. Why would simplify need to perform type checking to know that this pattern is incorrect?

You are right. Probably no type checking is required.

MartinThoma commented 2 years ago
$ astpretty --no-show-offsets /dev/stdin <<< `cat bad-example1.py`
Module(
    body=[
        Assign(
            targets=[Name(id='foo', ctx=Store())],
            value=Constant(value='bar', kind=None),
            type_comment=None,
        ),
        Assign(
            targets=[Name(id='my_text', ctx=Store())],
            value=JoinedStr(
                values=[
                    FormattedValue(
                        value=Name(id='foo', ctx=Load()),
                        conversion=-1,
                        format_spec=None,
                    ),
                ],
            ),
            type_comment=None,
        ),
    ],
    type_ignores=[],
)
MartinThoma commented 2 years ago
$ astpretty --no-show-offsets /dev/stdin <<< `cat bad-example2.py`
Module(
    body=[
        FunctionDef(
            name='my_func',
            args=arguments(
                posonlyargs=[],
                args=[
                    arg(
                        arg='foo',
                        annotation=Name(id='str', ctx=Load()),
                        type_comment=None,
                    ),
                ],
                vararg=None,
                kwonlyargs=[],
                kw_defaults=[],
                kwarg=None,
                defaults=[],
            ),
            body=[
                Assign(
                    targets=[Name(id='my_text', ctx=Store())],
                    value=JoinedStr(
                        values=[
                            FormattedValue(
                                value=Name(id='foo', ctx=Load()),
                                conversion=-1,
                                format_spec=None,
                            ),
                        ],
                    ),
                    type_comment=None,
                ),
            ],
            decorator_list=[],
            returns=None,
            type_comment=None,
        ),
    ],
    type_ignores=[],
)
MartinThoma commented 2 years ago
$ astpretty --no-show-offsets /dev/stdin <<< `cat bad-example3.py`
Module(
    body=[
        Assign(
            targets=[Name(id='my_number', ctx=Store())],
            value=Constant(value=123, kind=None),
            type_comment=None,
        ),
        Assign(
            targets=[Name(id='my_text', ctx=Store())],
            value=JoinedStr(
                values=[
                    FormattedValue(
                        value=Name(id='foo', ctx=Load()),
                        conversion=-1,
                        format_spec=None,
                    ),
                ],
            ),
            type_comment=None,
        ),
    ],
    type_ignores=[],
)
MartinThoma commented 2 years ago

Aparently f-strings are ast.JoinedStr and the parameters are automatically parsed. Variables are ast.FormattedValue. So we can recognize when we have an f-string.