Skip to content

Commit

Permalink
Tighten design constraints (#8115)
Browse files Browse the repository at this point in the history
* Lower max locals

* Lower max statements

* Lower max try statements

* Lower max branches

* Lower max args

* Cut design constraints with default values
  • Loading branch information
nickdrozd authored Jan 28, 2023
1 parent acb28d8 commit af555ed
Show file tree
Hide file tree
Showing 21 changed files with 37 additions and 29 deletions.
1 change: 1 addition & 0 deletions pylint/checkers/base/basic_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def report_by_type_stats(
sect.append(reporter_nodes.Table(children=lines, cols=6, rheaders=1))


# pylint: disable-next = too-many-public-methods
class BasicChecker(_BasicChecker):
"""Basic checker.
Expand Down
3 changes: 3 additions & 0 deletions pylint/checkers/classes/class_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,7 @@ def _check_attribute_defined_outside_init(self, cnode: nodes.ClassDef) -> None:
"attribute-defined-outside-init", args=attr, node=node
)

# pylint: disable = too-many-branches
def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""Check method arguments, overriding."""
# ignore actual functions
Expand Down Expand Up @@ -1218,6 +1219,7 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
pass

# check if the method is hidden by an attribute
# pylint: disable = too-many-try-statements
try:
overridden = klass.instance_attr(node.name)[0]
overridden_frame = overridden.frame(future=True)
Expand Down Expand Up @@ -2063,6 +2065,7 @@ def _check_init(self, node: nodes.FunctionDef, klass_node: nodes.ClassDef) -> No
and expr.expr.func.name == "super"
):
return
# pylint: disable = too-many-try-statements
try:
for klass in expr.expr.infer():
if klass is astroid.Uninferable:
Expand Down
2 changes: 1 addition & 1 deletion pylint/checkers/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def new_line(self, tokens: TokenWrapper, line_end: int, line_start: int) -> None
def process_module(self, node: nodes.Module) -> None:
pass

# pylint: disable-next=too-many-return-statements
# pylint: disable-next = too-many-return-statements, too-many-branches
def _check_keyword_parentheses(
self, tokens: list[tokenize.TokenInfo], start: int
) -> None:
Expand Down
1 change: 1 addition & 0 deletions pylint/checkers/imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ def _is_fallback_import(
imports = [import_node for (import_node, _) in imports]
return any(astroid.are_exclusive(import_node, node) for import_node in imports)

# pylint: disable = too-many-statements
def _check_imports_order(
self, _module_node: nodes.Module
) -> tuple[
Expand Down
1 change: 1 addition & 0 deletions pylint/checkers/refactoring/refactoring_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ def visit_if(self, node: nodes.If) -> None:
self._check_consider_get(node)
self._check_consider_using_min_max_builtin(node)

# pylint: disable = too-many-branches
def _check_consider_using_min_max_builtin(self, node: nodes.If) -> None:
"""Check if the given if node can be refactored as a min/max python builtin."""
if self._is_actual_elif(node) or node.orelse:
Expand Down
1 change: 1 addition & 0 deletions pylint/checkers/similar.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ def _get_similarity_report(
)
return report

# pylint: disable = too-many-locals
def _find_common(
self, lineset1: LineSet, lineset2: LineSet
) -> Generator[Commonality, None, None]:
Expand Down
1 change: 1 addition & 0 deletions pylint/checkers/spelling.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ def open(self) -> None:
)
self.initialized = True

# pylint: disable = too-many-statements
def _check_spelling(self, msgid: str, line: str, line_num: int) -> None:
original_line = line
try:
Expand Down
1 change: 1 addition & 0 deletions pylint/checkers/stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ def _check_lru_cache_decorators(self, node: nodes.FunctionDef) -> None:

lru_cache_nodes: list[nodes.NodeNG] = []
for d_node in node.decorators.nodes:
# pylint: disable = too-many-try-statements
try:
for infered_node in d_node.infer():
q_name = infered_node.qname()
Expand Down
3 changes: 2 additions & 1 deletion pylint/checkers/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ class StringFormatChecker(BaseChecker):
name = "string"
msgs = MSGS

# pylint: disable=too-many-branches
# pylint: disable = too-many-branches, too-many-locals, too-many-statements
@only_required_for_messages(
"bad-format-character",
"truncated-format-string",
Expand Down Expand Up @@ -533,6 +533,7 @@ def _check_new_format(self, node: nodes.Call, func: bases.BoundMethod) -> None:
self._detect_vacuous_formatting(node, positional_arguments)
self._check_new_format_specifiers(node, fields, named_arguments)

# pylint: disable = too-many-statements
def _check_new_format_specifiers(
self,
node: nodes.Call,
Expand Down
5 changes: 3 additions & 2 deletions pylint/checkers/typecheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ def _emit_no_member(
AttributeError, Exception or bare except.
* The node is guarded behind and `IF` or `IFExp` node
"""
# pylint: disable=too-many-return-statements
# pylint: disable = too-many-return-statements, too-many-branches
if node_ignores_exception(node, AttributeError):
return False
if ignored_none and isinstance(owner, nodes.Const) and owner.value is None:
Expand Down Expand Up @@ -1035,6 +1035,7 @@ def visit_assignattr(self, node: nodes.AssignAttr) -> None:
def visit_delattr(self, node: nodes.DelAttr) -> None:
self.visit_attribute(node)

# pylint: disable = too-many-branches
@only_required_for_messages("no-member", "c-extension-no-member")
def visit_attribute(
self, node: nodes.Attribute | nodes.AssignAttr | nodes.DelAttr
Expand Down Expand Up @@ -1399,7 +1400,7 @@ def _check_isinstance_args(self, node: nodes.Call) -> None:
if _is_invalid_isinstance_type(second_arg):
self.add_message("isinstance-second-argument-not-valid-type", node=node)

# pylint: disable=too-many-branches,too-many-locals
# pylint: disable = too-many-branches, too-many-locals, too-many-statements
def visit_call(self, node: nodes.Call) -> None:
"""Check that called functions/methods are inferred to callable objects,
and that passed arguments match the parameters in the inferred function.
Expand Down
4 changes: 4 additions & 0 deletions pylint/checkers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ def is_defined_in_scope(
return defnode_in_scope(var_node, varname, scope) is not None


# pylint: disable = too-many-branches
def defnode_in_scope(
var_node: nodes.NodeNG,
varname: str,
Expand Down Expand Up @@ -627,6 +628,7 @@ def collect_string_fields(format_string: str) -> Iterable[str | None]:
It handles nested fields as well.
"""
formatter = string.Formatter()
# pylint: disable = too-many-try-statements
try:
parseiterator = formatter.parse(format_string)
for result in parseiterator:
Expand Down Expand Up @@ -1374,6 +1376,7 @@ def safe_infer(
if value is not astroid.Uninferable:
inferred_types.add(_get_python_type_of_node(value))

# pylint: disable = too-many-try-statements
try:
for inferred in infer_gen:
inferred_type = _get_python_type_of_node(inferred)
Expand Down Expand Up @@ -2050,6 +2053,7 @@ def is_hashable(node: nodes.NodeNG) -> bool:
When finding ambiguity, return True.
"""
# pylint: disable = too-many-try-statements
try:
for inferred in node.infer():
if inferred is astroid.Uninferable or isinstance(inferred, nodes.ClassDef):
Expand Down
6 changes: 5 additions & 1 deletion pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,7 @@ def _should_node_be_skipped(

return False

# pylint: disable=too-many-return-statements
# pylint: disable = too-many-return-statements, too-many-branches
def _check_consumer(
self,
node: nodes.Name,
Expand Down Expand Up @@ -2025,6 +2025,7 @@ def _in_lambda_or_comprehension_body(
parent = parent.parent
return False

# pylint: disable = too-many-statements, too-many-branches
@staticmethod
def _is_variable_violation(
node: nodes.Name,
Expand Down Expand Up @@ -2402,6 +2403,7 @@ class D(Tp):
and name in frame_locals
)

# pylint: disable = too-many-branches
def _loopvar_name(self, node: astroid.Name) -> None:
# filter variables according to node's scope
astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
Expand Down Expand Up @@ -2546,6 +2548,7 @@ def _loopvar_name(self, node: astroid.Name) -> None:
if not elements:
self.add_message("undefined-loop-variable", args=node.name, node=node)

# pylint: disable = too-many-branches
def _check_is_unused(
self,
name: str,
Expand Down Expand Up @@ -3011,6 +3014,7 @@ def _check_globals(self, not_consumed: dict[str, nodes.NodeNG]) -> None:
for node in node_lst:
self.add_message("unused-variable", args=(name,), node=node)

# pylint: disable = too-many-branches
def _check_imports(self, not_consumed: dict[str, list[nodes.NodeNG]]) -> None:
local_names = _fix_dot_imports(not_consumed)
checked = set()
Expand Down
1 change: 1 addition & 0 deletions pylint/lint/expand_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def _is_ignored_file(
)


# pylint: disable = too-many-locals, too-many-statements
def expand_modules(
files_or_modules: Sequence[str],
ignore_list: list[str],
Expand Down
1 change: 1 addition & 0 deletions pylint/lint/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class Run:
Used by _PylintConfigRun to make the 'pylint-config' command work.
"""

# pylint: disable = too-many-statements, too-many-branches
def __init__(
self,
args: Sequence[str],
Expand Down
1 change: 1 addition & 0 deletions pylint/testutils/output_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def from_csv(
if isinstance(row, str):
row = row.split(",")
# noinspection PyBroadException
# pylint: disable = too-many-try-statements
try:
column = cls._get_column(row[2])
if len(row) == 5:
Expand Down
1 change: 1 addition & 0 deletions pylint/utils/ast_walker.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def walk(self, astroid: nodes.NodeNG) -> None:
visit_events: Sequence[AstCallback] = self.visit_events.get(cid, ())
leave_events: Sequence[AstCallback] = self.leave_events.get(cid, ())

# pylint: disable = too-many-try-statements
try:
if astroid.is_statement:
self.nbstatements += 1
Expand Down
29 changes: 5 additions & 24 deletions pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -411,44 +411,25 @@ max-spelling-suggestions=2
[DESIGN]

# Maximum number of arguments for function / method
max-args=10
max-args = 9

# Maximum number of locals for function / method body
max-locals=25
max-locals = 19

# Maximum number of return / yield for function / method body
max-returns=11

# Maximum number of branch for function / method body
max-branches=27
max-branches = 20

# Maximum number of statements in function / method body
max-statements=100

# Maximum number of parents for a class (see R0901).
max-parents=7

# List of qualified class names to ignore when counting class parents (see R0901).
ignored-parents=
max-statements = 50

# Maximum number of attributes for a class (see R0902).
max-attributes=11

# Minimum number of public methods for a class (see R0903).
min-public-methods=2

# Maximum number of public methods for a class (see R0904).
max-public-methods=25

# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5

# Maximum number of statements in a try-block
max-try-statements = 14

# List of regular expressions of class ancestor names to
# ignore when counting public methods (see R0903).
exclude-too-few-public-methods=
max-try-statements = 7

[CLASSES]

Expand Down
1 change: 1 addition & 0 deletions tests/checkers/unittest_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def deprecated_decorators(self) -> set[str]:
return {".deprecated_decorator"}


# pylint: disable-next = too-many-public-methods
class TestDeprecatedChecker(CheckerTestCase):
CHECKER_CLASS = _DeprecatedChecker

Expand Down
1 change: 1 addition & 0 deletions tests/checkers/unittest_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ def test_disable_global_option_end_of_line() -> None:
1
"""
)
# pylint: disable = too-many-try-statements
try:
linter = lint.PyLinter()
checker = BasicChecker(linter)
Expand Down
1 change: 1 addition & 0 deletions tests/lint/unittest_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,7 @@ def test_pylintrc() -> None:
with fake_home():
current_dir = getcwd()
chdir(os.path.dirname(os.path.abspath(sys.executable)))
# pylint: disable = too-many-try-statements
try:
with pytest.warns(DeprecationWarning):
assert config.find_pylintrc() is None
Expand Down
1 change: 1 addition & 0 deletions tests/test_self.py
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ def test_fail_on_edge_case(self, opts: list[str], out: int) -> None:

@staticmethod
def test_modify_sys_path() -> None:
# pylint: disable = too-many-statements
cwd = "/tmp/pytest-of-root/pytest-0/test_do_not_import_files_from_0"
default_paths = [
"/usr/local/lib/python39.zip",
Expand Down

0 comments on commit af555ed

Please sign in to comment.