Skip to content

Commit

Permalink
Add categories to checks (#109):
Browse files Browse the repository at this point in the history
This adds categories to each of the checks, though there is no way to enable
or disable checks based off of their category (yet).
  • Loading branch information
dosisod authored Nov 11, 2022
1 parent 6c3f05b commit 74bec8d
Show file tree
Hide file tree
Showing 38 changed files with 175 additions and 2 deletions.
100 changes: 100 additions & 0 deletions docs/categories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Categories

Here is a list of the built-in categories in Refurb, and their meanings.

## `builtin`

Checks that have the `builtin` category cover a few different topics:

* Built-in functions such as `print()`, `open()`, `str()`, and so on
* Statements such as `del`
* File system related operations such as `open()` and `readlines()`

## `control-flow`

These checks deal with the control flow of a program, such as optimizing usage
of `return` and `continue`, removing `if` statements under certain conditions,
and so on.

## `contextlib`

These checks are for the [contextlib](https://docs.python.org/3/library/contextlib.html)
standard library module.

## `dict`

These checks cover:

* Usage of `dict` objects
* In some cases, objects supporting the [Mapping](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping) protocol

## `fstring`

These checks relate to Python's [f-strings](https://fstring.help/).

## `functools`

These checks relate to the [functools](https://docs.python.org/3/library/functools.html)
standard library module.

## `iterable`

These checks cover:

* Iterable types such as `list` and `tuple`
* Standard library objects which are commonly iterated over such as `dict` keys

## `itertools`

These checks relate to the [itertools](https://docs.python.org/3/library/itertools.html)
standard library module.

## `operator`

These checks relate to the [operator](https://docs.python.org/3/library/operator.html)
standard library module.

## `logical`

These checks relate to logical cleanups and optimizations, primarily in `if` statements,
but also in boolean expressions.

## `list`

These checks cover usage of the built-in `list` object.

## `pathlib`

These checks relate to the [pathlib](https://docs.python.org/3/library/pathlib.html)
standard library module.

## `pythonic`

This is a general catch-all for things which are "unpythonic". It differs from the
`readability` category because "unreadable" code can still be pythonic.

## `readability`

These checks aim to make existing code more readable. This can be subjective, but in general,
they reduce the horizontal or vertical length of your code, or make the underlying meaning
of the code more apparent.

## `scoping`

These checks have to do with Python's scoping rules. For more info on how Python's scoping
rules work, read [this article](https://realpython.com/python-scope-legb-rule/).

## `string`

These checks deal with usage of [`str`](https://docs.python.org/3/library/stdtypes.html#string-methods)
objects in Python.

## `set`

These checks deal with usage of [`set`](https://docs.python.org/3/tutorial/datastructures.html#sets)
objects in Python.

## `truthy`

These checks cover truthy and falsy operations in Python, primarily in the context of `assert` and `if`
statements.
1 change: 1 addition & 0 deletions refurb/checks/builtin/list_extend.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ErrorInfo(Error):

code = 113
msg: str = "Use `x.extend(...)` instead of repeatedly calling `x.append()`"
categories = ["list"]


@dataclass
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/builtin/no_del.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ErrorInfo(Error):
"""

code = 131
categories = ["builtin", "readability"]


def check(node: DelStmt, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/builtin/no_ignored_dict_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class ErrorInfo(Error):
"""

code = 135
categories = ["dict"]


def check(
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/builtin/print.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ErrorInfo(Error):

code = 105
msg: str = 'Replace `print("")` with `print()`'
categories = ["builtin", "readability"]


def check(node: CallExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/builtin/set_discard.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class ErrorInfo(Error):

code = 132
msg: str = "Replace `if x in s: s.remove(x)` with `s.discard(x)`"
categories = ["readability", "set"]


def check(node: IfStmt, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/builtin/use_isinstance_tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ErrorInfo(Error):
"""

code = 121
categories = ["readability"]


def check(node: OpExpr, errors: list[Error], settings: Settings) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/builtin/writelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ErrorInfo(Error):

code = 122
msg: str = "Replace `for line in lines: f.write(line)` with `f.writelines(lines)`" # noqa: E501
categories = ["builtin", "readability"]


def check(node: WithStmt, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/contextlib/with_suppress.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ErrorInfo(Error):
"""

code = 107
categories = ["contextlib", "readability"]


def check(node: TryStmt, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/flow/no_trailing_continue.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def func2(x):

code = 133
msg: str = "Continue is redundant here"
categories = ["control-flow", "readability"]


def get_trailing_continue(node: Statement) -> Generator[Statement, None, None]:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/flow/no_trailing_return.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def func2(x):

code = 125
msg: str = "Return is redundant here"
categories = ["control-flow", "readability"]


def get_trailing_return(node: Statement) -> Generator[Statement, None, None]:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/flow/no_with_assign.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class ErrorInfo(Error):

code = 127
msg: str = "This variable is redeclared later, and can be removed here"
categories = ["readability", "scoping"]


def check(node: Block | MypyFile, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/flow/simplify_return.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def is_on_axis(position: tuple[int, int]) -> bool:
"""

code = 126
categories = ["control-flow", "readability"]


def get_trailing_return(node: Statement) -> Statement | None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/functools/use_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def f(x: int) -> int:

code = 134
msg: str = "Replace `@lru_cache(maxsize=None)` with `@cache`"
categories = ["functools", "readability"]


def check(node: Decorator, errors: list[Error], settings: Settings) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/iterable/implicit_readlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ErrorInfo(Error):

code = 129
msg: str = "Replace `f.readlines()` with `f`"
categories = ["builtin", "readability"]


def get_readline_file_object(expr: Expression) -> NameExpr | None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/iterable/in_tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ErrorInfo(Error):
"""

code = 109
categories = ["iterable", "readability"]


def error_msg(oper: str) -> str:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/logical/use_equal_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ErrorInfo(Error):

code = 124
msg: str = "Replace `x == y and x == z` with `x == y == z`"
categories = ["logical", "readability"]


def has_common_expr(*exprs: Expression) -> bool:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/logical/use_in.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ErrorInfo(Error):

code = 108
msg: str = "Replace `x == y or x == z` with `x in (y, z)`"
categories = ["logical", "readability"]


def check(node: OpExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/logical/use_or.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ErrorInfo(Error):

code = 110
msg: str = "Replace `x if x else y` with `x or y`"
categories = ["logical", "readability"]


def check(node: ConditionalExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/pathlib/cwd.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ErrorInfo(Error):

code = 104
msg: str = "Replace `os.getcwd()` with `Path.cwd()`"
categories = ["pathlib"]


def check(node: CallExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/pathlib/open.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ErrorInfo(Error):
"""

code = 117
categories = ["pathlib"]


def check(node: CallExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/pathlib/read_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ErrorInfo(Error):
"""

code = 101
categories = ["pathlib"]


def check(node: WithStmt, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/pathlib/with_suffix.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class ErrorInfo(Error):

code = 100
msg: str = "Use `Path(x).with_suffix(y)` instead of slice and concat" # noqa: E501
categories = ["pathlib"]


def check(node: OpExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/pathlib/write_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ErrorInfo(Error):
"""

code = 103
categories = ["pathlib"]


def check(node: WithStmt, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/in_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ErrorInfo(Error):
"""

code = 130
categories = ["dict", "readability"]


def check(node: ComparisonExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/no_double_not.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ErrorInfo(Error):

code = 114
msg: str = "Replace `not not x` with `bool(x)`"
categories = ["builtin", "readability", "truthy"]


def check(node: UnaryExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/no_len_cmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class ErrorInfo(Error):
"""

code = 115
categories = ["iterable", "truthy"]


CONTAINER_TYPES = {
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/no_unnecessary_cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ErrorInfo(Error):
"""

code = 123
categories = ["readability"]


FUNC_NAMES = {
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/use_func_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ErrorInfo(Error):

code = 111
msg: str = "Replace `lambda x: f(x)` with `f`"
categories = ["readability"]


def get_lambda_arg_names(args: list[Argument]) -> list[str]:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/use_literal.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ErrorInfo(Error):
"""

code = 112
categories = ["pythonic", "readability"]


FUNC_NAMES = {
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/use_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class ErrorInfo(Error):
"""

code = 118
categories = ["operator"]


BINARY_OPERATORS = {
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/readability/use_tuple_swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ErrorInfo(Error):

code = 128
msg: str = "Use tuple unpacking instead of temporary variables to swap values" # noqa: E501
categories = ["readability"]


def check(node: Block | MypyFile, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/string/expandtabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ErrorInfo(Error):

enabled = False
code = 106
categories = ["string"]


def check_str(node: CallExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/string/fstring_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ErrorInfo(Error):
"""

code = 116
categories = ["builtin", "fstring"]


FUNC_CONVERSIONS = {
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/string/startswith.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ErrorInfo(Error):
"""

code = 102
categories = ["string"]


def check(node: OpExpr, errors: list[Error]) -> None:
Expand Down
1 change: 1 addition & 0 deletions refurb/checks/string/use_fstring_fmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ErrorInfo(Error):
"""

code = 119
categories = ["builtin", "fstring"]


CONVERSIONS = {
Expand Down
5 changes: 3 additions & 2 deletions refurb/error.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import ClassVar, Optional
from typing import ClassVar


@dataclass(frozen=True)
Expand All @@ -25,7 +25,8 @@ class Error:
line: int
column: int
msg: str
filename: Optional[str] = None
filename: str | None = None
categories: list[str] | None = None

def __str__(self) -> str:
return f"{self.filename}:{self.line}:{self.column + 1} [{self.prefix}{self.code}]: {self.msg}" # noqa: E501
Loading

0 comments on commit 74bec8d

Please sign in to comment.