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 hour
s and minute
s
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.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size flake8_pie-0.7.1-py3-none-any.whl (65.7 kB) | File type Wheel | Python version py3 | Upload date | Hashes View |
Filename, size flake8-pie-0.7.1.tar.gz (17.3 kB) | File type Source | Python version None | Upload date | Hashes View |
Hashes for flake8_pie-0.7.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b75f7b0383a7c7b2660a86491d0cefd9d8c0eb47caae36064157f47b7c864a81 |
|
MD5 | f9e5f563acdbfdabf7fd167b4dc1502d |
|
BLAKE2-256 | da1fb30f3da168537ca195d09a2ef74327ffde881e78e39f713707bc53f2ca0e |