Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions flake8_idom_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
get_distribution as _get_distribution,
DistributionNotFound as _DistributionNotFound,
)
from typing import List, Tuple, Iterator, Union, Optional
from typing import List, Tuple, Iterator, Union, Optional, Type


try:
Expand All @@ -23,7 +23,7 @@ class Plugin:
def __init__(self, tree: ast.Module):
self._tree = tree

def run(self):
def run(self) -> List[Tuple[int, int, str, Type["Plugin"]]]:
visitor = HookRulesVisitor()
visitor.visit(self._tree)
cls = type(self)
Expand Down Expand Up @@ -66,8 +66,8 @@ def _visit_loop(self, node: ast.AST) -> None:

def _check_if_hook_defined_in_function(self, node: ast.FunctionDef) -> None:
if self._current_function is not None and _is_hook_or_element_def(node):
msg = f"Hook {node.name!r} defined inside another function."
self.errors.append((node.lineno, node.col_offset, msg))
msg = f"hook {node.name!r} defined as closure in function {self._current_function.name!r}"
self._save_error(100, node, msg)

def _check_if_propper_hook_usage(self, node: Union[ast.Name, ast.Attribute]):
if isinstance(node, ast.Name):
Expand All @@ -79,8 +79,8 @@ def _check_if_propper_hook_usage(self, node: Union[ast.Name, ast.Attribute]):
return

if not _is_hook_or_element_def(self._current_function):
msg = f"Hook {name!r} used outside element or hook definition."
self.errors.append((node.lineno, node.col_offset, msg))
msg = f"hook {name!r} used outside element or hook definition"
self._save_error(101, node, msg)
return

_loop_or_conditional = self._current_conditional or self._current_loop
Expand All @@ -94,10 +94,13 @@ def _check_if_propper_hook_usage(self, node: Union[ast.Name, ast.Attribute]):
ast.While: "while loop",
}
node_name = node_type_to_name[node_type]
msg = f"Hook {name!r} used inside {node_name}."
self.errors.append((node.lineno, node.col_offset, msg))
msg = f"hook {name!r} used inside {node_name}"
self._save_error(102, node, msg)
return

def _save_error(self, error_code: int, node: ast.AST, message: str):
self.errors.append((node.lineno, node.col_offset, f"ROH{error_code} {message}"))

@contextmanager
def _set_current(self, **attrs) -> Iterator[None]:
old_attrs = {k: getattr(self, f"_current_{k}") for k in attrs}
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-r requirements/dev.txt
-r requirements/prod.txt
-r requirements/test.txt
-r requirements/lint.txt
2 changes: 1 addition & 1 deletion requirements/lint.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
flake8
flake8 >=3.7
black
1 change: 1 addition & 0 deletions requirements/prod.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
flake8 >=3.7
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
ignore = E203, E266, E501, W503, F811, N802
max-line-length = 88
max-complexity = 18
select = B,C,E,F,W,T4,B9,N
exclude =
.eggs/*
.tox/*
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package = {
"name": name,
"py_modules": ["flake8_idom_hooks"],
"entry_points": {"flake8.extension": ["IDML = flake8_idom_hooks:Plugin"]},
"entry_points": {"flake8.extension": ["ROH=flake8_idom_hooks:Plugin"]},
"python_requires": ">=3.6",
"description": "Flake8 plugin to enforce the rules of hooks for IDOM",
"author": "Ryan Morshead",
Expand Down
26 changes: 13 additions & 13 deletions tests/hook_usage_cases.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
def HookInIf():
if True:
# error: Hook 'use_state' used inside if statement.
# error: ROH102 hook 'use_state' used inside if statement
use_state


def HookInElif():
if False:
pass
elif True:
# error: Hook 'use_state' used inside if statement.
# error: ROH102 hook 'use_state' used inside if statement
use_state


def HookInElse():
if False:
pass
else:
# error: Hook 'use_state' used inside if statement.
# error: ROH102 hook 'use_state' used inside if statement
use_state


def HookInIfExp():
(
# error: Hook 'use_state' used inside inline if expression.
# error: ROH102 hook 'use_state' used inside inline if expression
use_state
if True
else None
Expand All @@ -34,14 +34,14 @@ def HookInElseOfIfExp():
None
if True
else
# error: Hook 'use_state' used inside inline if expression.
# error: ROH102 hook 'use_state' used inside inline if expression
use_state
)


def HookInTry():
try:
# error: Hook 'use_state' used inside try statement.
# error: ROH102 hook 'use_state' used inside try statement
use_state
except:
pass
Expand All @@ -51,38 +51,38 @@ def HookInExcept():
try:
raise ValueError()
except:
# error: Hook 'use_state' used inside try statement.
# error: ROH102 hook 'use_state' used inside try statement
use_state


def HookInFinally():
try:
pass
finally:
# error: Hook 'use_state' used inside try statement.
# error: ROH102 hook 'use_state' used inside try statement
use_state


def HookInForLoop():
for i in range(3):
# error: Hook 'use_state' used inside for loop.
# error: ROH102 hook 'use_state' used inside for loop
use_state


def HookInWhileLoop():
while True:
# error: Hook 'use_state' used inside while loop.
# error: ROH102 hook 'use_state' used inside while loop
use_state


def outer_function():
# error: Hook 'use_state' defined inside another function.
# error: ROH100 hook 'use_state' defined as closure in function 'outer_function'
def use_state():
...


def generic_function():
# error: Hook 'use_state' used outside element or hook definition.
# error: ROH101 hook 'use_state' used outside element or hook definition
use_state


Expand All @@ -97,5 +97,5 @@ def Element():
# ok since 'use_state' is not the last attribute
module.use_state.other

# error: Hook 'use_state' used outside element or hook definition.
# error: ROH101 hook 'use_state' used outside element or hook definition
module.use_state