Formatting#
Lint Checks#
To ensure that Ivy is always formatted correctly, flake8 is used to run lint checks on all Python files in the CI. Some of the main things which flake8 checks for are listed below.
Imports
Module imports are checked to detect:
unused imports
module imported but not used
module used without imports
duplicate imports
undefined import names
Syntax
Flake8 is useful in detecting syntax errors, which are one of the most common mistakes. Some examples are:
break
orcontinue
statement outside afor
orwhile
loopcontinue
statement in thefinally
block of a loopyield
oryield from
statement outside a functionreturn
statement used with arguments in a generator, or outside a function or methodexcept:
block not being the last exception handlersyntax or length errors in docstrings, comments, or annotations
Literals
Literals formatting are often used in a string statement; some common checks related to this are:
invalid
%
format%
format with missing arguments or unsupported character.format(...)
with invalid format, missing or unused argumentsf-string without placeholders
Others
There are many more types of checks which flake8
can perform.
These include but are not limited to:
repeated
dict
key or variable assigned to different valuesstar-unpacking assignment with too many expressions
assertion test is a
tuple
, which is alwaystrue
use of
==
or!=
to comparestr
,bytes
orint
literalsraise NotImplemented
should beraise NotImplementedError
Pre-Commit Hook#
In Ivy, we try our best to avoid committing code with lint errors. To achieve this, we make use of the pre-commit package. The installation is explained in the pre-commit guide.
The pre-commit hook runs the flake8
lint checks before each commit.
This is efficient and useful in preventing errors being pushed to the repository.
In the case where errors are found, error messages will be raised and committing will be unsuccessful until the mistake is corrected. If the errors are related to argument formatting, it will be reformatted automatically.
For example, the line length limit might be exceeded if arguments are all added in a single line of code like so:
def argwhere(
x: Union[ivy.Array, ivy.NativeArray], *, out: Optional[ivy.Array] = None,
) -> ivy.Array:
When a commit is attempted, pre-commit would detect this error by running the lint check, and it would then reformat the arguments automatically.
black....................................................................Failed
- hook id: black
- files were modified by this hook
reformatted ivy/functional/ivy/general.py
All done! ✨ 🍰 ✨
1 file reformatted.
flake8...................................................................Passed
The above message indicates that a file disobeying the formatting rules is detected and reformatting has taken place successfully. The correctly formatted code, with each argument added on a new line, has been saved and the related file(s) can now be staged and committed accordingly.
def argwhere(
x: Union[ivy.Array, ivy.NativeArray],
*,
out: Optional[ivy.Array] = None,
) -> ivy.Array:
If the code is all formatted correctly, then in this case pre-commit will not modify the code.
For example, when the line limit is not exceeded by the function arguments, then the arguments should indeed be listed on the same line, together with the function def(...)
syntax, as shown below.
def iinfo(type: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray]) -> Iinfo:
This would pass the lint checks, and pre-commit
would allow the code to be committed without error.
black....................................................................Passed
flake8...................................................................Passed
Round Up
This should have hopefully given you a good feel for how function wrapping is applied to functions in Ivy.
If you have any questions, please feel free to reach out on `discord`_ in the formatting channel or in the formatting forum!
Video