Custom flake8 rules
- TUT100 (DEPRECATED, covered by 502) - dataclass class variables require annotations
- Notes: you can trick this rule by renaming dataclass - and there is the potential for some false positives
- TUT101 - dataclasses.dataclass cannot be renamed in import
- Notes: this is meant to act against the major case of false negatives for TUT100
- TUT2:
- TUT200 - asyncio.create_task requires the name parameter
- TUT201 - asyncio.create_task is either
awaited or assigned to a variable- See
Importanthere on garbage collection for motivation
- See
- TUT210 - async function call either
awaitorasync fororasync with- If the body of the function is either
passor immediately errors or immediately returns, the function is excused - It is expected that some class functions will fail this rule, but it still has utility
- If the body of the function is either
- TUT220 - no async function in a
catchblock that will catch a cancelled error orfinallythat is not one ofasyncio.wait_for,asyncio.waitorasyncio.sleep, prevents running forever when task is cancelled - TUT230 - any call to
cancelis passed a message (that is not aNoneliteral)- This is a highly opinionated as it assumes that any
cancelcall that matches the spec ofasyncio.Task.cancelis on a task. To enforce this properly you would use typing, but that is a more aggressive step to take
- This is a highly opinionated as it assumes that any
- TUT300 - no expressions in the main body, unless under name == "main", prevents global side effects
- TUT4:
- TUT400 - detect strings that were likely meant to be f-strings
- TODO: we should exclude regex-es
- TUT410 - detect redundant type annotations
- TUT411 - detect redundant type annotations for generic assignment
- Don't do
x: Foo[bar] = Foo(); dox = Foo[bar]()
- Don't do
- TUT400 - detect strings that were likely meant to be f-strings
- TUT5
- TUT500 (DEPRECATED: covered by 502/503 + mypy) - instance variables set in
__init__cannot overlap with class variables - TUT501 - class variables must be defined before all functions
- TUT502 - class variables must be type annotated
- with exceptions for Enum and IntEnum
- It is safe to ignore this rule in the case where the variable is inherited - this is hard to detect in flake though
- TUT503 - class variables must be annotated as ClassVar or Final, with exceptions for:
- dataclasses
- NamedTuple
- Protocol
- Enum and IntEnum
- TypedDict
- pydantic BaseModel and pydantic-numpy NumpyModel
- TUT510 - No two argument
superwithin a class - TUT511 - A child class must call a parent classes method for
__init__- Skips if inherited from certain classes:
Generic,ABC,Protocol,collections.abcand specific defined subclasses - Additional classes to skip are configurable with
non-init-classes
- Skips if inherited from certain classes:
- TUT512 - A child class must call a parent classes method for
__post_init__- All the same exceptions as 511
- TUT520 -
NotImplementedis only allowed within a dunder method on a class- Any other usage is very likely incorrect
- TUT530 - a constructor must return
Selftype rather than the class type- This encourages good use of constructors that play well with inheritence
- We detect methods whose return type includes the class type without having any input of the type
- TUT500 (DEPRECATED: covered by 502/503 + mypy) - instance variables set in
- TUT6
- TUT610 - a function definition allows too many positional arguments (configurable with
max-definition-positional-args) - TUT620 - a function invocation uses too many positional arguments (configurable with
max-invocation-positional-args) - TUT630 - a function definition has two consecutive positional arguments with identical typing
- Positional only or key word only arguments are excluded
- This is to help prevent arguments where ordering matters being misordered but still passing typing
- TUT610 - a function definition allows too many positional arguments (configurable with
- TUT7
- TUT700 - Prevent
os.path.<func>()function calls - TUT710 - Prevent
from os import path - TUT720 - Prevent
import os.path
- TUT700 - Prevent
- TUT8
- TUT800 - Prevent
time.time- Note: programmers often use
time.timeto extract time deltas in seconds, rather than actually fetching the numbers of seconds since the epoch. This has tricky pitfalls, such as clock sync jumps and lack of monotonicity guarantees.
- Note: programmers often use
- TUT810 - Prevent
from time import time(see TUT800)
- TUT800 - Prevent
- Enforce calling await on async methods
- I would like to do this - but I don't know how to identify if a method is async
- No addition of string literals (or f-strings)
- Should we also forbid
os.walk - Fixtures must end in
_fixt - Constants must be uppercase
- Empty
ifblocks should be disallowed- Motivated by empty
if TYPE_CHECKING
- Motivated by empty
In a pyproject.toml, can install like this:
tutor-flake = {git = "ssh://[email protected]/tutorintelligence/tutor_flake.git", rev = "v0.2.0"}
To configure, in setup.cfg
[flake8:local-plugins]
extension =
TUT = tutor_flake.plugin:TutorIntelligenceFlakePlugin