docstyle.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # Copyright (c) 2016-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
  2. # Copyright (c) 2016 Łukasz Rogalski <rogalski.91@gmail.com>
  3. # Copyright (c) 2016 Luis Escobar <lescobar@vauxoo.com>
  4. # Copyright (c) 2019, 2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>
  5. # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
  6. # Copyright (c) 2020 Anthony Sottile <asottile@umich.edu>
  7. # Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
  8. # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>
  9. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  10. # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
  11. import linecache
  12. from astroid import nodes
  13. from pylint import checkers
  14. from pylint.checkers.utils import check_messages
  15. from pylint.interfaces import HIGH, IAstroidChecker
  16. class DocStringStyleChecker(checkers.BaseChecker):
  17. """Checks format of docstrings based on PEP 0257"""
  18. __implements__ = IAstroidChecker
  19. name = "docstyle"
  20. msgs = {
  21. "C0198": (
  22. 'Bad docstring quotes in %s, expected """, given %s',
  23. "bad-docstring-quotes",
  24. "Used when a docstring does not have triple double quotes.",
  25. ),
  26. "C0199": (
  27. "First line empty in %s docstring",
  28. "docstring-first-line-empty",
  29. "Used when a blank line is found at the beginning of a docstring.",
  30. ),
  31. }
  32. @check_messages("docstring-first-line-empty", "bad-docstring-quotes")
  33. def visit_module(self, node: nodes.Module) -> None:
  34. self._check_docstring("module", node)
  35. def visit_classdef(self, node: nodes.ClassDef) -> None:
  36. self._check_docstring("class", node)
  37. def visit_functiondef(self, node: nodes.FunctionDef) -> None:
  38. ftype = "method" if node.is_method() else "function"
  39. self._check_docstring(ftype, node)
  40. visit_asyncfunctiondef = visit_functiondef
  41. def _check_docstring(self, node_type, node):
  42. docstring = node.doc
  43. if docstring and docstring[0] == "\n":
  44. self.add_message(
  45. "docstring-first-line-empty",
  46. node=node,
  47. args=(node_type,),
  48. confidence=HIGH,
  49. )
  50. # Use "linecache", instead of node.as_string(), because the latter
  51. # looses the original form of the docstrings.
  52. if docstring:
  53. lineno = node.fromlineno + 1
  54. line = linecache.getline(node.root().file, lineno).lstrip()
  55. if line and line.find('"""') == 0:
  56. return
  57. if line and "'''" in line:
  58. quotes = "'''"
  59. elif line and line[0] == '"':
  60. quotes = '"'
  61. elif line and line[0] == "'":
  62. quotes = "'"
  63. else:
  64. quotes = False
  65. if quotes:
  66. self.add_message(
  67. "bad-docstring-quotes",
  68. node=node,
  69. args=(node_type, quotes),
  70. confidence=HIGH,
  71. )
  72. def register(linter):
  73. """Required method to auto register this checker.
  74. :param linter: Main interface object for Pylint plugins
  75. :type linter: Pylint object
  76. """
  77. linter.register_checker(DocStringStyleChecker(linter))