astral-sh/ruff

Implement flake8-pie

sbdchd opened this issue · 8 comments

There might be some overlap with these rules and pylint / flake8-simplify, but I think I eliminated most of the dupes / unnecessary rules:

  • PIE810: single-starts-ends-with
    Instead of calling startswith or endswith on the same string for multiple prefixes, pass the prefixes as a tuple in a single startswith or endswith call.
# error
foo.startswith("foo") or foo.startswith("bar")

# error
foo.endswith("foo") or foo.endswith("bar")

# error
foo.startswith("foo") or str.startswith(foo, "bar")

# ok
foo.startswith(("foo",  "bar"))

# ok
foo.endswith(("foo",  "bar"))

# ok
foo.startswith("foo") or foo.endswith("bar")

pass is unnecessary when definining a class or function with an empty body.

# error
class BadError(Exception):
    """
    some doc comment
    """
    pass

def foo() -> None:
    """
    some function
    """
    pass

# ok
class BadError(Exception):
    """
    some doc comment
    """

def foo() -> None:
    """
    some function
    """

Finds duplicate definitions for the same field, which can occur in large ORM model definitions.

# error
class User(BaseModel):
    email = fields.EmailField()
    # ...80 more properties...
    email = fields.EmailField()

# ok
class User(BaseModel):
    email = fields.EmailField()
    # ...80 more properties...

By default the stdlib enum allows multiple field names to map to the same value, this lint requires each enum value be unique.

# error
class Foo(enum.Enum):
    A = "A"
    B = "B"
    C = "C"
    D = "C"

# ok
class Foo(enum.Enum):
    A = "A"
    B = "B"
    C = "C"
    D = "D"

Check for unnecessary dict unpacking.

# error
{**foo, **{"bar": 10}}

# ok
{**foo, "bar": 10}

As long as the keys of the dict are valid Python identifier names, we can safely remove the surrounding dict.

# error
foo(**{"bar": True})

# ok
foo(bar=True)
foo(**buzz)
foo(**{"bar foo": True})

lambda: [] is equivalent to the builtin list

# error
@dataclass
class Foo:
    foo: List[str] = field(default_factory=lambda: [])

# ok
@dataclass
class Foo:
    foo: List[str] = field(default_factory=list)

Do these all sound good / are there any I should leave out? I skipped a few different ones from the original package that were too specific / awkward.

Also skipped rules that overlapped with:

Yeah these are all quite nice. I can try to implement one of them tomorrow to lay the groundwork for the plugin and we can run from there.

(Thanks for this thoughtful collation.)

I didn't realize you actually wrote that plugin, very cool.

I was passing by and was wondering if can i write some of these ? I'm actually learning rust, but, these plugins look easy enough.

I actually got around to developing the prefer_unique_enums rule last night 😅 and i made a mistake with a PR so i closed it 😓

@ljesparis - Yes please, thanks!

@sbdchd - Are you planning to do PIE810 to close this one out? Just trying to keep tabs on who's working on what. Thanks!

Yeah I can do that one as well

Gonna close this for now, can always do that final rule if anyone wants to grab it.