A flake8 extension that implements misc. lints
Project description
flake8-pie

A flake8 extension that implements misc. lints
lints
PIE781: assign-and-return
Based on Clippy's
let_and_return
and Microsoft's TSLint rule
no-unnecessary-local-variable.
For more info on the structure of this lint, see the accompanying blog post.
examples
# error
def foo():
x = bar()
return x
# allowed
def foo():
x, _ = bar()
return x
PIE783: celery-explicit-names
Warn about Celery task definitions that don't have explicit names.
Note: this lint is kind of naive considering any decorator with a .task()
method or any decorator called shared_task() a Celery decorator.
examples
# error
@app.task()
def foo():
pass
# ok
@app.task(name="app_name.tasks.foo")
def foo():
pass
PIE784: celery-explicit-crontab-args
The crontab class provided by Celery has some default args that are
suprising to new users. Specifically, crontab(hour="0,12") won't run a task
at midnight and noon, it will run the task at every minute during those two
hours. This lint makes that call an error, forcing you to write
crontab(hour="0, 12", minute="*").
Additionally, the lint is a bit more complex in that it requires you specify
every smaller increment than the largest time increment you provide. So if you
provide days_of_week, then you need to provide hours and minutes
explicitly.
Note: if you like the default behavior of crontab() then you can either
disable this lint or pass "*" for the kwarg value, e.g., minutes="*".
Also, since this lint is essentially a naive search for calls to a
crontab() function, if you have a function named the same then this will
cause false positives.
PIE785: celery-require-tasks-expire
Celery tasks can bunch up if they don't have expirations.
This enforces specifying expirations in both the celery beat config dict and
in .apply_async() calls.
The same caveat applies about how this lint is naive.
PIE786: precise-exception-handlers
Be precise in what exceptions you catch. Bare except: handlers, catching BaseException, or catching Exception can lead to unexpected bugs.
examples
# error
try:
save_file(name="export.csv")
except:
pass
# error
try:
save_file(name="export.csv")
except BaseException:
pass
# error
try:
save_file(name="export.csv")
except Exception:
pass
# error
try:
save_file(name="export.csv")
except (ValueError, Exception):
pass
# ok
try:
save_file(name="export.csv")
except OSError:
pass
PIE787: no-len-condition
Empty collections are fasley in Python so calling len() is unnecessary when
checking for emptiness in an if statement/expression.
Comparing to explicit scalars is allowed.
# error
if len(foo): ...
if not len(foo): ...
# ok
if foo: ...
if not foo: ...
if len(foo) > 0: ...
if len(foo) == 0: ...
PIE788: no-bool-condition
If statements/expressions evalute the truthiness of the their test argument,
so calling bool() is unnecessary.
Comparing to True/False is allowed.
# error
if bool(foo): ...
if not bool(foo): ...
# ok
if foo: ...
if not foo: ...
if bool(foo) is True: ...
if bool(foo) is False: ...
PIE789: prefer-isinstance-type-compare
Using type() doesn't take into account subclassess and type checkers won't
refine the type, use isinstance instead.
# error
if type(foo) == str: ...
if type(foo) is str: ...
if type(foo) in [int, str]: ...
# ok
if isinstance(foo, str): ...
if isinstance(foo, (int, str)): ...
PIE790: no-unnecessary-pass
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
"""
PIE791: no-pointless-statements
Comparisions without an assignment or assertion are probably a typo.
# error
"foobar" in data
res.json() == []
user.is_authenticated() is True
# ok
assert "foobar" in data
foo = res.json() == []
use.is_authenticated()
PIE792: no-inherit-object
Inheriting from object isn't necessary in Python 3.
# error
class Foo(object):
...
# ok
class Foo:
...
PIE793: prefer-dataclass
Attempts to find cases where the @dataclass decorator is unintentionally
missing.
# error
class Foo:
z: dict[int, int]
def __init__(self) -> None: ...
class Bar:
x: list[str]
# ok
class Bar(Foo):
z: dict[int, int]
@dataclass
class Bar:
x: list[str]
PIE794: dupe-class-field-definitions
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...
PIE795: prefer-stdlib-enums
Instead of defining various constant properties on a class, use the stdlib enum which typecheckers support for type refinement.
# error
class Foo:
A = "A"
B = "B"
C = "C"
# ok
import enum
class Foo(enum.Enum):
A = "A"
B = "B"
C = "C"
PIE796: prefer-unique-enums
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"
PIE797: no-unecessary-if-expr
Call bool() directly rather than reimplementing its functionality.
# error
foo(is_valid=True if buzz() else False)
# ok
foo(is_valid=bool(buzz()))
dev
# install dependencies
poetry install
s/lint
s/test
uploading a new version to PyPi
# increment `Flake8PieCheck.version` and pyproject.toml `version`
# build new distribution files and upload to pypi
# Note: this will ask for login credentials
rm -rf dist && poetry publish --build
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flake8-pie-0.7.1.tar.gz.
File metadata
- Download URL: flake8-pie-0.7.1.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/0.12.11 CPython/3.7.0 Darwin/20.3.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
198baa85d85dea2bc42c28baa5978bc771fced814bac9a9688441efe65485711
|
|
| MD5 |
50682c510fb7c29555ab9f8b0cdddf2a
|
|
| BLAKE2b-256 |
1ff4c4212b0465e5b3916153d399df938d51d1b276fade31390a5d263fb252fe
|
File details
Details for the file flake8_pie-0.7.1-py3-none-any.whl.
File metadata
- Download URL: flake8_pie-0.7.1-py3-none-any.whl
- Upload date:
- Size: 65.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/0.12.11 CPython/3.7.0 Darwin/20.3.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b75f7b0383a7c7b2660a86491d0cefd9d8c0eb47caae36064157f47b7c864a81
|
|
| MD5 |
f9e5f563acdbfdabf7fd167b4dc1502d
|
|
| BLAKE2b-256 |
da1fb30f3da168537ca195d09a2ef74327ffde881e78e39f713707bc53f2ca0e
|