-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix false positive DOC203 in property methods (#115)
- Loading branch information
Showing
9 changed files
with
151 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import ast | ||
|
||
from pydoclint.utils.astTypes import FuncOrAsyncFuncDef | ||
|
||
|
||
def checkIsAbstractMethod(node: FuncOrAsyncFuncDef) -> bool: | ||
"""Check whether `node` is an abstract method""" | ||
return checkMethodContainsSpecifiedDecorator(node, 'abstractmethod') | ||
|
||
|
||
def checkIsPropertyMethod(node: FuncOrAsyncFuncDef) -> bool: | ||
"""Check whether `node` is a method with @property decorator""" | ||
return checkMethodContainsSpecifiedDecorator(node, 'property') | ||
|
||
|
||
def checkMethodContainsSpecifiedDecorator( | ||
node: FuncOrAsyncFuncDef, | ||
decorator: str, | ||
) -> bool: | ||
"""Check whether a method is decorated by the specified decorator""" | ||
return ( | ||
isinstance(node.decorator_list, list) | ||
and len(node.decorator_list) > 0 | ||
and any( | ||
( # noqa: PAR001 | ||
isinstance(_, ast.Name) | ||
and hasattr(node.decorator_list[-1], 'id') | ||
and _.id == decorator | ||
) | ||
for _ in node.decorator_list | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
class MyClass: | ||
data: float = 2.1 | ||
|
||
@property | ||
def something(self) -> float: | ||
""" | ||
Some property. | ||
It's OK to have no return section in this method, because this | ||
is a "property method" and is intended to be used as an attribute. | ||
""" | ||
return self.data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import ast | ||
from typing import Optional | ||
|
||
import pytest | ||
|
||
from pydoclint.utils.special_methods import ( | ||
checkMethodContainsSpecifiedDecorator, | ||
) | ||
|
||
src1 = """ | ||
class A: | ||
def method1(self): | ||
pass | ||
""" | ||
|
||
src2 = """ | ||
class A: | ||
@property | ||
def method1(self): | ||
pass | ||
""" | ||
|
||
src3 = """ | ||
class A: | ||
@hello | ||
@world | ||
@property | ||
@morning | ||
def method1(self): | ||
pass | ||
""" | ||
|
||
src4 = """ | ||
# pydoclint only does static code analysis in order to achieve fast speed. | ||
# If users rename built-in decorator names (such as `property`), pydoclint | ||
# will not recognize it. | ||
hello_world = property | ||
class A: | ||
@hello_world | ||
def method1(self): | ||
pass | ||
""" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'src, decorator, expected', | ||
[ | ||
(src1, 'something', False), | ||
(src2, 'property', True), | ||
(src3, 'property', True), | ||
(src4, 'hello_world', True), | ||
(src4, 'property', False), | ||
], | ||
) | ||
def testCheckMethodContainsSpecifiedDecorator( | ||
src: str, | ||
decorator: str, | ||
expected: bool, | ||
) -> None: | ||
def getMethod1(tree_: ast.AST) -> Optional[ast.FunctionDef]: | ||
for node_ in ast.walk(tree_): | ||
if isinstance(node_, ast.FunctionDef) and node_.name == 'method1': | ||
return node_ | ||
|
||
return None | ||
|
||
tree = ast.parse(src) | ||
node = getMethod1(tree) | ||
result = checkMethodContainsSpecifiedDecorator(node, decorator=decorator) | ||
assert result == expected |