mirror of
https://github.com/zebrajr/pytorch.git
synced 2025-12-06 00:20:18 +01:00
Pull Request resolved: https://github.com/pytorch/pytorch/pull/151906 Approved by: https://github.com/Skylion007
This commit is contained in:
parent
9210a98b92
commit
2825a28bf1
|
|
@ -8,7 +8,7 @@ import token
|
|||
from enum import Enum
|
||||
from functools import cached_property, total_ordering
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, TYPE_CHECKING
|
||||
from typing import Any, Callable, Optional, TYPE_CHECKING
|
||||
from typing_extensions import Self
|
||||
|
||||
|
||||
|
|
@ -34,10 +34,15 @@ MAX_LINES = {"class": 100, "def": 80}
|
|||
|
||||
MIN_DOCSTRING = 50 # docstrings shorter than this are too short
|
||||
|
||||
ERROR_FMT = "Every {type} with more than {length} lines needs a docstring"
|
||||
DESCRIPTION = """
|
||||
`docstring_linter` reports on long functions, methods or classes without docstrings
|
||||
""".strip()
|
||||
|
||||
DESCRIPTION = """`docstring_linter` reports on long functions, methods or classes
|
||||
without docstrings"""
|
||||
METHOD_OVERRIDE_HINT = (
|
||||
"If the method overrides a method on a parent class, adding the"
|
||||
" `@typing_extensions.override` decorator will make this error"
|
||||
" go away."
|
||||
)
|
||||
|
||||
|
||||
@total_ordering
|
||||
|
|
@ -87,7 +92,7 @@ class Block:
|
|||
is_method: bool = dc.field(default=False, repr=False)
|
||||
|
||||
# A block index to the parent of this block, or None for a top-level block.
|
||||
parent: int | None = None
|
||||
parent: Optional[int] = None
|
||||
|
||||
# A list of block indexes for the children
|
||||
children: list[int] = dc.field(default_factory=list)
|
||||
|
|
@ -114,9 +119,25 @@ class Block:
|
|||
ending = "" if self.is_class else "()"
|
||||
return f"{self.category.value} {self.full_name}{ending}"
|
||||
|
||||
@cached_property
|
||||
def decorators(self) -> list[str]:
|
||||
"""A list of decorators for this function or method.
|
||||
|
||||
Each decorator both the @ symbol and any arguments to the decorator
|
||||
but no extra whitespace.
|
||||
"""
|
||||
return _get_decorators(self.tokens, self.begin)
|
||||
|
||||
@cached_property
|
||||
def is_override(self) -> bool:
|
||||
return not self.is_class and any(
|
||||
d.rpartition(".")[2] == "override" for d in self.decorators
|
||||
)
|
||||
|
||||
DATA_FIELDS = (
|
||||
"category",
|
||||
"children",
|
||||
"decorators",
|
||||
"display_name",
|
||||
"docstring",
|
||||
"full_name",
|
||||
|
|
@ -152,6 +173,33 @@ class Block:
|
|||
return o.index < self.index
|
||||
|
||||
|
||||
_IGNORE = {token.COMMENT, token.DEDENT, token.INDENT, token.NL}
|
||||
|
||||
|
||||
def _get_decorators(tokens: Sequence[TokenInfo], block_start: int) -> list[str]:
|
||||
def decorators() -> Iterator[str]:
|
||||
rev = reversed(range(block_start))
|
||||
newlines = (i for i in rev if tokens[i].type == token.NEWLINE)
|
||||
newlines = itertools.chain(newlines, [-1]) # To account for the first line
|
||||
|
||||
it = iter(newlines)
|
||||
end = next(it, -1) # Like itertools.pairwise in Python 3.10
|
||||
for begin in it:
|
||||
for i in range(begin + 1, end):
|
||||
t = tokens[i]
|
||||
if t.type == token.OP and t.string == "@":
|
||||
useful = (t for t in tokens[i:end] if t.type not in _IGNORE)
|
||||
yield "".join(s.string.strip("\n") for s in useful)
|
||||
break
|
||||
elif t.type not in _IGNORE:
|
||||
return # A statement means no more decorators
|
||||
end = begin
|
||||
|
||||
out = list(decorators())
|
||||
out.reverse()
|
||||
return out
|
||||
|
||||
|
||||
class DocstringFile(_linter.PythonFile):
|
||||
def __getitem__(self, i: int | slice) -> TokenInfo | Sequence[TokenInfo]:
|
||||
return self.tokens[i]
|
||||
|
|
@ -337,9 +385,13 @@ class DocstringLinter(_linter.FileLinter[DocstringFile]):
|
|||
def_name = "function" if b.category == "def" else "class"
|
||||
msg = f"docstring found for {def_name} '{b.name}' ({b.line_count} lines)"
|
||||
if len(b.docstring):
|
||||
msg = msg + f" was too short ({len(b.docstring)} characters)"
|
||||
s = "" if len(b.docstring) == 1 else "s"
|
||||
needed = f"needed {self.args.min_docstring}"
|
||||
msg = f"{msg} was too short ({len(b.docstring)} character{s}, {needed})"
|
||||
else:
|
||||
msg = "No " + msg
|
||||
msg = f"No {msg}"
|
||||
if b.is_method:
|
||||
msg = f"{msg}. {METHOD_OVERRIDE_HINT}"
|
||||
return _linter.LintResult(msg, *df.tokens[b.begin].start)
|
||||
|
||||
def _display(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ tools/test/docstring_linter_testdata/python_code.py.txt:17: No docstring found f
|
|||
18 | # A comment isn't a docstring
|
||||
19 |
|
||||
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:24: docstring found for class 'LongWithShortDocstring' (6 lines) was too short (10 characters)
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:24: docstring found for class 'LongWithShortDocstring' (6 lines) was too short (10 characters, needed 16)
|
||||
22 |
|
||||
23 |
|
||||
24 | class LongWithShortDocstring:
|
||||
|
|
@ -22,7 +22,7 @@ tools/test/docstring_linter_testdata/python_code.py.txt:24: docstring found for
|
|||
25 | """TODO"""
|
||||
26 |
|
||||
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:71: No docstring found for function 'needs_docs' (12 lines)
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:71: No docstring found for function 'needs_docs' (12 lines). If the method overrides a method on a parent class, adding the `@typing_extensions.override` decorator will make this error go away.
|
||||
69 | """This docstring, while short, is enough"""
|
||||
70 |
|
||||
71 | def needs_docs(self):
|
||||
|
|
|
|||
|
|
@ -81,12 +81,21 @@ class ImpossibleCombo(
|
|||
pass
|
||||
|
||||
|
||||
@override # Won't work!
|
||||
class NotDocstring:
|
||||
def short1(self):
|
||||
pass
|
||||
|
||||
"""This is not a docstring"""
|
||||
|
||||
@override
|
||||
def long_with_override(self):
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
pass
|
||||
|
||||
def short2(self):
|
||||
pass
|
||||
|
||||
|
|
@ -94,6 +103,7 @@ class NotDocstring:
|
|||
pass
|
||||
|
||||
|
||||
|
||||
def long_with_omit(): # noqa: docstring_linter
|
||||
#
|
||||
#
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
"code": "DOCSTRING_LINTER",
|
||||
"description": null,
|
||||
"line": 24,
|
||||
"name": "docstring found for class 'LongWithShortDocstring' (6 lines) was too short (10 characters)",
|
||||
"name": "docstring found for class 'LongWithShortDocstring' (6 lines) was too short (10 characters, needed 16)",
|
||||
"original": null,
|
||||
"path": "tools/test/docstring_linter_testdata/python_code.py.txt",
|
||||
"replacement": null,
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
"code": "DOCSTRING_LINTER",
|
||||
"description": null,
|
||||
"line": 71,
|
||||
"name": "No docstring found for function 'needs_docs' (12 lines)",
|
||||
"name": "No docstring found for function 'needs_docs' (12 lines). If the method overrides a method on a parent class, adding the `@typing_extensions.override` decorator will make this error go away.",
|
||||
"original": null,
|
||||
"path": "tools/test/docstring_linter_testdata/python_code.py.txt",
|
||||
"replacement": null,
|
||||
|
|
@ -38,9 +38,9 @@
|
|||
"description": null,
|
||||
"line": null,
|
||||
"name": "Suggested fixes for docstring_linter",
|
||||
"original": "class ShortWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n pass\n\n\nclass Short:\n pass\n\n\nclass LongWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def short1(self):\n pass\n\n\nclass LongWithoutDocstring:\n # A comment isn't a docstring\n\n def short1(self):\n pass\n\n\nclass LongWithShortDocstring:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\nclass _Protected:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\ndef short():\n #\n #\n #\n pass\n\n\ndef long():\n \"\"\"This docstring, while short, is enough\"\"\"\n #\n #\n #\n #\n pass\n\n\ndef long_without_docstring():\n #\n #\n #\n #\n pass\n\n\nclass ImpossibleCombo(\n set,\n tuple,\n int,\n):\n # We could have comments\n # before the doc comment\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def needs_docs(self):\n def not_short():\n class Long:\n a = 1\n b = 1\n c = 1\n d = 1\n e = 1\n\n class Short:\n pass\n\n\nclass NotDocstring:\n def short1(self):\n pass\n\n \"\"\"This is not a docstring\"\"\"\n\n def short2(self):\n pass\n\n def short3(self):\n pass\n\n\ndef long_with_omit(): # noqa: docstring_linter\n #\n #\n #\n #\n pass\n",
|
||||
"original": "class ShortWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n pass\n\n\nclass Short:\n pass\n\n\nclass LongWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def short1(self):\n pass\n\n\nclass LongWithoutDocstring:\n # A comment isn't a docstring\n\n def short1(self):\n pass\n\n\nclass LongWithShortDocstring:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\nclass _Protected:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\ndef short():\n #\n #\n #\n pass\n\n\ndef long():\n \"\"\"This docstring, while short, is enough\"\"\"\n #\n #\n #\n #\n pass\n\n\ndef long_without_docstring():\n #\n #\n #\n #\n pass\n\n\nclass ImpossibleCombo(\n set,\n tuple,\n int,\n):\n # We could have comments\n # before the doc comment\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def needs_docs(self):\n def not_short():\n class Long:\n a = 1\n b = 1\n c = 1\n d = 1\n e = 1\n\n class Short:\n pass\n\n\n@override # Won't work!\nclass NotDocstring:\n def short1(self):\n pass\n\n \"\"\"This is not a docstring\"\"\"\n\n @override\n def long_with_override(self):\n #\n #\n #\n #\n pass\n\n def short2(self):\n pass\n\n def short3(self):\n pass\n\n\n\ndef long_with_omit(): # noqa: docstring_linter\n #\n #\n #\n #\n pass\n",
|
||||
"path": "tools/test/docstring_linter_testdata/python_code.py.txt",
|
||||
"replacement": "class ShortWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n pass\n\n\nclass Short:\n pass\n\n\nclass LongWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def short1(self):\n pass\n\n\nclass LongWithoutDocstring:\n # A comment isn't a docstring\n\n def short1(self):\n pass\n\n\nclass LongWithShortDocstring:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\nclass _Protected:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\ndef short():\n #\n #\n #\n pass\n\n\ndef long():\n \"\"\"This docstring, while short, is enough\"\"\"\n #\n #\n #\n #\n pass\n\n\ndef long_without_docstring():\n #\n #\n #\n #\n pass\n\n\nclass ImpossibleCombo(\n set,\n tuple,\n int,\n):\n # We could have comments\n # before the doc comment\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def needs_docs(self):\n def not_short():\n class Long:\n a = 1\n b = 1\n c = 1\n d = 1\n e = 1\n\n class Short:\n pass\n\n\nclass NotDocstring:\n def short1(self):\n pass\n\n \"\"\"This is not a docstring\"\"\"\n\n def short2(self):\n pass\n\n def short3(self):\n pass\n\n\ndef long_with_omit(): # noqa: docstring_linter\n #\n #\n #\n #\n pass\n",
|
||||
"replacement": "class ShortWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n pass\n\n\nclass Short:\n pass\n\n\nclass LongWithDocstring:\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def short1(self):\n pass\n\n\nclass LongWithoutDocstring:\n # A comment isn't a docstring\n\n def short1(self):\n pass\n\n\nclass LongWithShortDocstring:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\nclass _Protected:\n \"\"\"TODO\"\"\"\n\n def short1(self):\n pass\n\n\ndef short():\n #\n #\n #\n pass\n\n\ndef long():\n \"\"\"This docstring, while short, is enough\"\"\"\n #\n #\n #\n #\n pass\n\n\ndef long_without_docstring():\n #\n #\n #\n #\n pass\n\n\nclass ImpossibleCombo(\n set,\n tuple,\n int,\n):\n # We could have comments\n # before the doc comment\n \"\"\"This docstring, while short, is enough\"\"\"\n\n def needs_docs(self):\n def not_short():\n class Long:\n a = 1\n b = 1\n c = 1\n d = 1\n e = 1\n\n class Short:\n pass\n\n\n@override # Won't work!\nclass NotDocstring:\n def short1(self):\n pass\n\n \"\"\"This is not a docstring\"\"\"\n\n @override\n def long_with_override(self):\n #\n #\n #\n #\n pass\n\n def short2(self):\n pass\n\n def short3(self):\n pass\n\n\n\ndef long_with_omit(): # noqa: docstring_linter\n #\n #\n #\n #\n pass\n",
|
||||
"severity": "error"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ tools/test/docstring_linter_testdata/python_code.py.txt:17: No docstring found f
|
|||
18 | # A comment isn't a docstring
|
||||
19 |
|
||||
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:24: docstring found for class 'LongWithShortDocstring' (6 lines) was too short (10 characters)
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:24: docstring found for class 'LongWithShortDocstring' (6 lines) was too short (10 characters, needed 16)
|
||||
22 |
|
||||
23 |
|
||||
24 | class LongWithShortDocstring:
|
||||
|
|
@ -14,7 +14,7 @@ tools/test/docstring_linter_testdata/python_code.py.txt:24: docstring found for
|
|||
25 | """TODO"""
|
||||
26 |
|
||||
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:71: No docstring found for function 'needs_docs' (12 lines)
|
||||
tools/test/docstring_linter_testdata/python_code.py.txt:71: No docstring found for function 'needs_docs' (12 lines). If the method overrides a method on a parent class, adding the `@typing_extensions.override` decorator will make this error go away.
|
||||
69 | """This docstring, while short, is enough"""
|
||||
70 |
|
||||
71 | def needs_docs(self):
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ShortWithDocstring",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "ShortWithDocstring",
|
||||
|
|
@ -15,6 +16,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class Short",
|
||||
"docstring": "",
|
||||
"full_name": "Short",
|
||||
|
|
@ -31,6 +33,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def LongWithDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithDocstring.short1",
|
||||
|
|
@ -42,6 +45,7 @@
|
|||
"start_line": 14
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class LongWithDocstring",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "LongWithDocstring",
|
||||
|
|
@ -58,6 +62,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def LongWithoutDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithoutDocstring.short1",
|
||||
|
|
@ -69,6 +74,7 @@
|
|||
"start_line": 21
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class LongWithoutDocstring",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithoutDocstring",
|
||||
|
|
@ -85,6 +91,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def LongWithShortDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithShortDocstring.short1",
|
||||
|
|
@ -96,6 +103,7 @@
|
|||
"start_line": 28
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class LongWithShortDocstring",
|
||||
"docstring": "\"\"\"TODO\"\"\"",
|
||||
"full_name": "LongWithShortDocstring",
|
||||
|
|
@ -112,6 +120,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def _Protected.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "_Protected.short1",
|
||||
|
|
@ -123,6 +132,7 @@
|
|||
"start_line": 35
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class _Protected",
|
||||
"docstring": "\"\"\"TODO\"\"\"",
|
||||
"full_name": "_Protected",
|
||||
|
|
@ -136,6 +146,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def short()",
|
||||
"docstring": "",
|
||||
"full_name": "short",
|
||||
|
|
@ -149,6 +160,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def long()",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "long",
|
||||
|
|
@ -162,6 +174,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def long_without_docstring()",
|
||||
"docstring": "",
|
||||
"full_name": "long_without_docstring",
|
||||
|
|
@ -184,6 +197,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Long",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Long",
|
||||
|
|
@ -197,6 +211,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Short",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Short",
|
||||
|
|
@ -208,6 +223,7 @@
|
|||
"start_line": 81
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "def ImpossibleCombo.needs_docs.not_short()",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short",
|
||||
|
|
@ -221,6 +237,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Long",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Long",
|
||||
|
|
@ -234,6 +251,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Short",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Short",
|
||||
|
|
@ -245,6 +263,7 @@
|
|||
"start_line": 81
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "def ImpossibleCombo.needs_docs()",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs",
|
||||
|
|
@ -261,6 +280,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Long",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Long",
|
||||
|
|
@ -274,6 +294,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Short",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Short",
|
||||
|
|
@ -285,6 +306,7 @@
|
|||
"start_line": 81
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "def ImpossibleCombo.needs_docs.not_short()",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short",
|
||||
|
|
@ -298,6 +320,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Long",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Long",
|
||||
|
|
@ -311,6 +334,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Short",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Short",
|
||||
|
|
@ -322,6 +346,7 @@
|
|||
"start_line": 81
|
||||
}
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "ImpossibleCombo",
|
||||
|
|
@ -338,6 +363,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def NotDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short1",
|
||||
|
|
@ -346,56 +372,78 @@
|
|||
"is_method": true,
|
||||
"line_count": 2,
|
||||
"parent": 18,
|
||||
"start_line": 86
|
||||
"start_line": 87
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"display_name": "def NotDocstring.short2()",
|
||||
"decorators": [
|
||||
"@override"
|
||||
],
|
||||
"display_name": "def NotDocstring.long_with_override()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short2",
|
||||
"full_name": "NotDocstring.long_with_override",
|
||||
"index": 20,
|
||||
"is_local": false,
|
||||
"is_method": true,
|
||||
"line_count": 2,
|
||||
"parent": 18,
|
||||
"start_line": 91
|
||||
"start_line": 97
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"display_name": "def NotDocstring.short3()",
|
||||
"decorators": [],
|
||||
"display_name": "def NotDocstring.short2()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short3",
|
||||
"full_name": "NotDocstring.short2",
|
||||
"index": 21,
|
||||
"is_local": false,
|
||||
"is_method": true,
|
||||
"line_count": 3,
|
||||
"line_count": 2,
|
||||
"parent": 18,
|
||||
"start_line": 94
|
||||
"start_line": 100
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def NotDocstring.short3()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short3",
|
||||
"index": 22,
|
||||
"is_local": false,
|
||||
"is_method": true,
|
||||
"line_count": 4,
|
||||
"parent": 18,
|
||||
"start_line": 103
|
||||
}
|
||||
],
|
||||
"decorators": [
|
||||
"@override"
|
||||
],
|
||||
"display_name": "class NotDocstring",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring",
|
||||
"index": 18,
|
||||
"is_local": false,
|
||||
"is_method": false,
|
||||
"line_count": 12,
|
||||
"line_count": 21,
|
||||
"parent": null,
|
||||
"start_line": 85
|
||||
"start_line": 86
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def long_with_omit()",
|
||||
"docstring": "",
|
||||
"full_name": "long_with_omit",
|
||||
"index": 22,
|
||||
"index": 23,
|
||||
"is_local": false,
|
||||
"is_method": false,
|
||||
"line_count": 1,
|
||||
"parent": null,
|
||||
"start_line": 102
|
||||
"start_line": 112
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -123,28 +123,34 @@
|
|||
},
|
||||
"class NotDocstring": {
|
||||
"children": {
|
||||
"86": {
|
||||
" 87": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.short1",
|
||||
"status": "good"
|
||||
},
|
||||
"91": {
|
||||
" 97": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.long_with_override",
|
||||
"status": "good"
|
||||
},
|
||||
"100": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.short2",
|
||||
"status": "good"
|
||||
},
|
||||
"94": {
|
||||
"103": {
|
||||
"docstring_len": 0,
|
||||
"lines": 3,
|
||||
"lines": 4,
|
||||
"name": "def NotDocstring.short3",
|
||||
"status": "good"
|
||||
}
|
||||
},
|
||||
"docstring_len": 0,
|
||||
"line": 85,
|
||||
"lines": 12,
|
||||
"line": 86,
|
||||
"lines": 21,
|
||||
"status": "good"
|
||||
},
|
||||
"class Short": {
|
||||
|
|
@ -181,7 +187,7 @@
|
|||
},
|
||||
"def long_with_omit": {
|
||||
"docstring_len": 0,
|
||||
"line": 102,
|
||||
"line": 112,
|
||||
"lines": 1,
|
||||
"status": "good"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -165,33 +165,39 @@
|
|||
"name": "class ImpossibleCombo",
|
||||
"status": "good"
|
||||
},
|
||||
" 85": {
|
||||
" 86": {
|
||||
"children": {
|
||||
"86": {
|
||||
" 87": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.short1",
|
||||
"status": "good"
|
||||
},
|
||||
"91": {
|
||||
" 97": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.long_with_override",
|
||||
"status": "good"
|
||||
},
|
||||
"100": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.short2",
|
||||
"status": "good"
|
||||
},
|
||||
"94": {
|
||||
"103": {
|
||||
"docstring_len": 0,
|
||||
"lines": 3,
|
||||
"lines": 4,
|
||||
"name": "def NotDocstring.short3",
|
||||
"status": "good"
|
||||
}
|
||||
},
|
||||
"docstring_len": 0,
|
||||
"lines": 12,
|
||||
"lines": 21,
|
||||
"name": "class NotDocstring",
|
||||
"status": "good"
|
||||
},
|
||||
"102": {
|
||||
"112": {
|
||||
"docstring_len": 0,
|
||||
"lines": 1,
|
||||
"name": "def long_with_omit",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ShortWithDocstring",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "ShortWithDocstring",
|
||||
|
|
@ -15,6 +16,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class Short",
|
||||
"docstring": "",
|
||||
"full_name": "Short",
|
||||
|
|
@ -30,6 +32,7 @@
|
|||
"children": [
|
||||
3
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class LongWithDocstring",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "LongWithDocstring",
|
||||
|
|
@ -43,6 +46,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def LongWithDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithDocstring.short1",
|
||||
|
|
@ -58,6 +62,7 @@
|
|||
"children": [
|
||||
5
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class LongWithoutDocstring",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithoutDocstring",
|
||||
|
|
@ -71,6 +76,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def LongWithoutDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithoutDocstring.short1",
|
||||
|
|
@ -86,6 +92,7 @@
|
|||
"children": [
|
||||
7
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class LongWithShortDocstring",
|
||||
"docstring": "\"\"\"TODO\"\"\"",
|
||||
"full_name": "LongWithShortDocstring",
|
||||
|
|
@ -99,6 +106,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def LongWithShortDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "LongWithShortDocstring.short1",
|
||||
|
|
@ -114,6 +122,7 @@
|
|||
"children": [
|
||||
9
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class _Protected",
|
||||
"docstring": "\"\"\"TODO\"\"\"",
|
||||
"full_name": "_Protected",
|
||||
|
|
@ -127,6 +136,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def _Protected.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "_Protected.short1",
|
||||
|
|
@ -140,6 +150,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def short()",
|
||||
"docstring": "",
|
||||
"full_name": "short",
|
||||
|
|
@ -153,6 +164,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def long()",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "long",
|
||||
|
|
@ -166,6 +178,7 @@
|
|||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def long_without_docstring()",
|
||||
"docstring": "",
|
||||
"full_name": "long_without_docstring",
|
||||
|
|
@ -184,6 +197,7 @@
|
|||
16,
|
||||
17
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo",
|
||||
"docstring": "\"\"\"This docstring, while short, is enough\"\"\"",
|
||||
"full_name": "ImpossibleCombo",
|
||||
|
|
@ -201,6 +215,7 @@
|
|||
16,
|
||||
17
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "def ImpossibleCombo.needs_docs()",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs",
|
||||
|
|
@ -217,6 +232,7 @@
|
|||
16,
|
||||
17
|
||||
],
|
||||
"decorators": [],
|
||||
"display_name": "def ImpossibleCombo.needs_docs.not_short()",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short",
|
||||
|
|
@ -230,6 +246,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Long",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Long",
|
||||
|
|
@ -243,6 +260,7 @@
|
|||
{
|
||||
"category": "class",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "class ImpossibleCombo.needs_docs.not_short.Short",
|
||||
"docstring": "",
|
||||
"full_name": "ImpossibleCombo.needs_docs.not_short.Short",
|
||||
|
|
@ -258,7 +276,11 @@
|
|||
"children": [
|
||||
19,
|
||||
20,
|
||||
21
|
||||
21,
|
||||
22
|
||||
],
|
||||
"decorators": [
|
||||
"@override"
|
||||
],
|
||||
"display_name": "class NotDocstring",
|
||||
"docstring": "",
|
||||
|
|
@ -266,13 +288,14 @@
|
|||
"index": 18,
|
||||
"is_local": false,
|
||||
"is_method": false,
|
||||
"line_count": 12,
|
||||
"line_count": 21,
|
||||
"parent": null,
|
||||
"start_line": 85
|
||||
"start_line": 86
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def NotDocstring.short1()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short1",
|
||||
|
|
@ -281,45 +304,64 @@
|
|||
"is_method": true,
|
||||
"line_count": 2,
|
||||
"parent": 18,
|
||||
"start_line": 86
|
||||
"start_line": 87
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"display_name": "def NotDocstring.short2()",
|
||||
"decorators": [
|
||||
"@override"
|
||||
],
|
||||
"display_name": "def NotDocstring.long_with_override()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short2",
|
||||
"full_name": "NotDocstring.long_with_override",
|
||||
"index": 20,
|
||||
"is_local": false,
|
||||
"is_method": true,
|
||||
"line_count": 2,
|
||||
"parent": 18,
|
||||
"start_line": 91
|
||||
"start_line": 97
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"display_name": "def NotDocstring.short3()",
|
||||
"decorators": [],
|
||||
"display_name": "def NotDocstring.short2()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short3",
|
||||
"full_name": "NotDocstring.short2",
|
||||
"index": 21,
|
||||
"is_local": false,
|
||||
"is_method": true,
|
||||
"line_count": 3,
|
||||
"line_count": 2,
|
||||
"parent": 18,
|
||||
"start_line": 94
|
||||
"start_line": 100
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def NotDocstring.short3()",
|
||||
"docstring": "",
|
||||
"full_name": "NotDocstring.short3",
|
||||
"index": 22,
|
||||
"is_local": false,
|
||||
"is_method": true,
|
||||
"line_count": 4,
|
||||
"parent": 18,
|
||||
"start_line": 103
|
||||
},
|
||||
{
|
||||
"category": "def",
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"display_name": "def long_with_omit()",
|
||||
"docstring": "",
|
||||
"full_name": "long_with_omit",
|
||||
"index": 22,
|
||||
"index": 23,
|
||||
"is_local": false,
|
||||
"is_method": false,
|
||||
"line_count": 1,
|
||||
"parent": null,
|
||||
"start_line": 102
|
||||
"start_line": 112
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@
|
|||
" 73": "def ImpossibleCombo.needs_docs.not_short(): lines=11, docs=0",
|
||||
" 74": "class ImpossibleCombo.needs_docs.not_short.Long: lines=6, docs=0",
|
||||
" 81": "class ImpossibleCombo.needs_docs.not_short.Short: lines=3, docs=0",
|
||||
" 85": "class NotDocstring: lines=12, docs=0",
|
||||
" 86": "def NotDocstring.short1(): lines=2, docs=0",
|
||||
" 91": "def NotDocstring.short2(): lines=2, docs=0",
|
||||
" 94": "def NotDocstring.short3(): lines=3, docs=0",
|
||||
"102": "def long_with_omit(): lines=1, docs=0"
|
||||
" 86": "class NotDocstring: lines=21, docs=0",
|
||||
" 87": "def NotDocstring.short1(): lines=2, docs=0",
|
||||
" 97": "def NotDocstring.long_with_override(): lines=2, docs=0",
|
||||
"100": "def NotDocstring.short2(): lines=2, docs=0",
|
||||
"103": "def NotDocstring.short3(): lines=4, docs=0",
|
||||
"112": "def long_with_omit(): lines=1, docs=0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@
|
|||
},
|
||||
"class NotDocstring": {
|
||||
"docstring_len": 0,
|
||||
"line": 85,
|
||||
"lines": 12,
|
||||
"line": 86,
|
||||
"lines": 21,
|
||||
"status": "good"
|
||||
},
|
||||
"class Short": {
|
||||
|
|
@ -89,22 +89,28 @@
|
|||
"lines": 3,
|
||||
"status": "good"
|
||||
},
|
||||
"def NotDocstring.long_with_override": {
|
||||
"docstring_len": 0,
|
||||
"line": 97,
|
||||
"lines": 2,
|
||||
"status": "good"
|
||||
},
|
||||
"def NotDocstring.short1": {
|
||||
"docstring_len": 0,
|
||||
"line": 86,
|
||||
"line": 87,
|
||||
"lines": 2,
|
||||
"status": "good"
|
||||
},
|
||||
"def NotDocstring.short2": {
|
||||
"docstring_len": 0,
|
||||
"line": 91,
|
||||
"line": 100,
|
||||
"lines": 2,
|
||||
"status": "good"
|
||||
},
|
||||
"def NotDocstring.short3": {
|
||||
"docstring_len": 0,
|
||||
"line": 94,
|
||||
"lines": 3,
|
||||
"line": 103,
|
||||
"lines": 4,
|
||||
"status": "good"
|
||||
},
|
||||
"def _Protected.short1": {
|
||||
|
|
@ -121,7 +127,7 @@
|
|||
},
|
||||
"def long_with_omit": {
|
||||
"docstring_len": 0,
|
||||
"line": 102,
|
||||
"line": 112,
|
||||
"lines": 1,
|
||||
"status": "good"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -107,31 +107,37 @@
|
|||
"name": "class ImpossibleCombo.needs_docs.not_short.Short",
|
||||
"status": "good"
|
||||
},
|
||||
" 85": {
|
||||
" 86": {
|
||||
"docstring_len": 0,
|
||||
"lines": 12,
|
||||
"lines": 21,
|
||||
"name": "class NotDocstring",
|
||||
"status": "good"
|
||||
},
|
||||
" 86": {
|
||||
" 87": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.short1",
|
||||
"status": "good"
|
||||
},
|
||||
" 91": {
|
||||
" 97": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.long_with_override",
|
||||
"status": "good"
|
||||
},
|
||||
"100": {
|
||||
"docstring_len": 0,
|
||||
"lines": 2,
|
||||
"name": "def NotDocstring.short2",
|
||||
"status": "good"
|
||||
},
|
||||
" 94": {
|
||||
"103": {
|
||||
"docstring_len": 0,
|
||||
"lines": 3,
|
||||
"lines": 4,
|
||||
"name": "def NotDocstring.short3",
|
||||
"status": "good"
|
||||
},
|
||||
"102": {
|
||||
"112": {
|
||||
"docstring_len": 0,
|
||||
"lines": 1,
|
||||
"name": "def long_with_omit",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# mypy: ignore-errors
|
||||
|
||||
import io
|
||||
import itertools
|
||||
import json
|
||||
import sys
|
||||
import tempfile
|
||||
|
|
@ -8,6 +9,7 @@ from pathlib import Path
|
|||
from unittest import mock
|
||||
|
||||
from tools.linter.adapters.docstring_linter import (
|
||||
_get_decorators,
|
||||
DocstringLinter,
|
||||
file_summary,
|
||||
make_recursive,
|
||||
|
|
@ -119,13 +121,26 @@ class TestDocstringLinter(LinterTestCase):
|
|||
]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_decorators(self):
|
||||
tests = itertools.product(INDENTS, DECORATORS.items())
|
||||
for indent, (name, (expected, test_inputs)) in tests:
|
||||
ind = indent * " "
|
||||
for data in test_inputs:
|
||||
prog = "".join(ind + d + "\n" for d in data)
|
||||
pf = DocstringLinter.make_file(prog)
|
||||
it = (i for i, t in enumerate(pf.tokens) if t.string == "def")
|
||||
def_t = next(it, 0)
|
||||
with self.subTest("Decorator", indent=indent, name=name, data=data):
|
||||
actual = list(_get_decorators(pf.tokens, def_t))
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
||||
def _dumps(d: dict) -> str:
|
||||
return json.dumps(d, sort_keys=True, indent=2) + "\n"
|
||||
|
||||
|
||||
def _data():
|
||||
docstring_file = DocstringLinter.make_file(TEST_FILE)
|
||||
def _data(file=TEST_FILE):
|
||||
docstring_file = DocstringLinter.make_file(file)
|
||||
return [b.as_data() for b in docstring_file.blocks]
|
||||
|
||||
|
||||
|
|
@ -135,3 +150,54 @@ def _next_stdout(mock_stdout):
|
|||
s = mock_stdout.getvalue()
|
||||
yield s[length:]
|
||||
length = len(s)
|
||||
|
||||
|
||||
CONSTANT = "A = 10"
|
||||
COMMENT = "# a simple function"
|
||||
OVER = "@override"
|
||||
WRAPS = "@functools.wraps(fn)"
|
||||
MASSIVE = (
|
||||
"@some.long.path.very_long_function_name(",
|
||||
" adjust_something_fiddly=1231232,",
|
||||
" disable_something_critical=True,)",
|
||||
)
|
||||
MASSIVE_FLAT = (
|
||||
"@some.long.path.very_long_function_name("
|
||||
"adjust_something_fiddly=1231232,"
|
||||
"disable_something_critical=True,)"
|
||||
)
|
||||
DEF = "def function():", " pass"
|
||||
|
||||
INDENTS = 0, 4, 8
|
||||
DECORATORS = {
|
||||
"none": (
|
||||
[],
|
||||
(
|
||||
[],
|
||||
[*DEF],
|
||||
[COMMENT, *DEF],
|
||||
[CONSTANT, "", COMMENT, *DEF],
|
||||
[OVER, CONSTANT, *DEF], # Probably not even Python. :-)
|
||||
),
|
||||
),
|
||||
"one": (
|
||||
[OVER],
|
||||
(
|
||||
[OVER, *DEF],
|
||||
[OVER, COMMENT, *DEF],
|
||||
[OVER, COMMENT, "", *DEF],
|
||||
[COMMENT, OVER, "", COMMENT, "", *DEF],
|
||||
),
|
||||
),
|
||||
"two": (
|
||||
[OVER, WRAPS],
|
||||
(
|
||||
[OVER, WRAPS, *DEF],
|
||||
[COMMENT, OVER, COMMENT, WRAPS, COMMENT, *DEF],
|
||||
),
|
||||
),
|
||||
"massive": (
|
||||
[MASSIVE_FLAT, OVER],
|
||||
([*MASSIVE, OVER, *DEF],),
|
||||
),
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user