Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_check_docs.py 57KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988
  1. # Copyright (c) 2014-2015 Bruno Daniel <bruno.daniel@blue-yonder.com>
  2. # Copyright (c) 2015-2017 Claudiu Popa <pcmanticore@gmail.com>
  3. # Copyright (c) 2016-2018 Ashley Whetter <ashley@awhetter.co.uk>
  4. # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
  5. # Copyright (c) 2016 Glenn Matthews <glenn@e-dad.net>
  6. # Copyright (c) 2016 Glenn Matthews <glmatthe@cisco.com>
  7. # Copyright (c) 2017 hippo91 <guillaume.peillex@gmail.com>
  8. # Copyright (c) 2017 Mitar <mitar.github@tnode.com>
  9. # Copyright (c) 2017 John Paraskevopoulos <io.paraskev@gmail.com>
  10. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  11. # For details: https://github.com/PyCQA/pylint/blob/master/COPYING
  12. """Unit tests for the pylint checkers in :mod:`pylint.extensions.check_docs`,
  13. in particular the parameter documentation checker `DocstringChecker`
  14. """
  15. from __future__ import division, print_function, absolute_import
  16. import sys
  17. import pytest
  18. import astroid
  19. from pylint.testutils import CheckerTestCase, Message, set_config
  20. from pylint.extensions.docparams import DocstringParameterChecker
  21. class TestParamDocChecker(CheckerTestCase):
  22. """Tests for pylint_plugin.ParamDocChecker"""
  23. CHECKER_CLASS = DocstringParameterChecker
  24. CONFIG = {
  25. 'accept_no_param_doc': False,
  26. }
  27. def test_missing_func_params_in_sphinx_docstring(self):
  28. """Example of a function with missing Sphinx parameter documentation in
  29. the docstring
  30. """
  31. node = astroid.extract_node("""
  32. def function_foo(x, y, z):
  33. '''docstring ...
  34. :param x: bla
  35. :param int z: bar
  36. '''
  37. pass
  38. """)
  39. with self.assertAddsMessages(
  40. Message(
  41. msg_id='missing-param-doc',
  42. node=node,
  43. args=('y',)),
  44. Message(
  45. msg_id='missing-type-doc',
  46. node=node,
  47. args=('x, y',))
  48. ):
  49. self.checker.visit_functiondef(node)
  50. def test_missing_func_params_in_google_docstring(self):
  51. """Example of a function with missing Google style parameter
  52. documentation in the docstring
  53. """
  54. node = astroid.extract_node("""
  55. def function_foo(x, y, z):
  56. '''docstring ...
  57. Args:
  58. x: bla
  59. z (int): bar
  60. some other stuff
  61. '''
  62. pass
  63. """)
  64. with self.assertAddsMessages(
  65. Message(
  66. msg_id='missing-param-doc',
  67. node=node,
  68. args=('y',)),
  69. Message(
  70. msg_id='missing-type-doc',
  71. node=node,
  72. args=('x, y',))
  73. ):
  74. self.checker.visit_functiondef(node)
  75. def test_func_params_and_keyword_params_in_google_docstring(self):
  76. """Example of a function with Google style parameter splitted
  77. in Args and Keyword Args in the docstring
  78. """
  79. node = astroid.extract_node("""
  80. def my_func(this, other, that=True):
  81. '''Prints this, other and that
  82. Args:
  83. this (str): Printed first
  84. other (int): Other args
  85. Keyword Args:
  86. that (bool): Printed second
  87. '''
  88. print(this, that, other)
  89. """)
  90. with self.assertNoMessages():
  91. self.checker.visit_functiondef(node)
  92. def test_func_params_and_wrong_keyword_params_in_google_docstring(self):
  93. """Example of a function with Google style parameter splitted
  94. in Args and Keyword Args in the docstring but with wrong keyword args
  95. """
  96. node = astroid.extract_node("""
  97. def my_func(this, other, that=True):
  98. '''Prints this, other and that
  99. Args:
  100. this (str): Printed first
  101. other (int): Other args
  102. Keyword Args:
  103. these (bool): Printed second
  104. '''
  105. print(this, that, other)
  106. """)
  107. with self.assertAddsMessages(
  108. Message(
  109. msg_id='missing-param-doc',
  110. node=node,
  111. args=('that',)),
  112. Message(
  113. msg_id='missing-type-doc',
  114. node=node,
  115. args=('that',)),
  116. Message(
  117. msg_id='differing-param-doc',
  118. node=node,
  119. args=('these',)),
  120. Message(
  121. msg_id='differing-type-doc',
  122. node=node,
  123. args=('these',))
  124. ):
  125. self.checker.visit_functiondef(node)
  126. def test_missing_func_params_in_numpy_docstring(self):
  127. """Example of a function with missing NumPy style parameter
  128. documentation in the docstring
  129. """
  130. node = astroid.extract_node("""
  131. def function_foo(x, y, z):
  132. '''docstring ...
  133. Parameters
  134. ----------
  135. x:
  136. bla
  137. z: int
  138. bar
  139. some other stuff
  140. '''
  141. pass
  142. """)
  143. with self.assertAddsMessages(
  144. Message(
  145. msg_id='missing-param-doc',
  146. node=node,
  147. args=('y',)),
  148. Message(
  149. msg_id='missing-type-doc',
  150. node=node,
  151. args=('x, y',))
  152. ):
  153. self.checker.visit_functiondef(node)
  154. @set_config(accept_no_param_doc=True)
  155. def test_tolerate_no_param_documentation_at_all(self):
  156. """Example of a function with no parameter documentation at all
  157. No error message is emitted.
  158. """
  159. node = astroid.extract_node("""
  160. def function_foo(x, y):
  161. '''docstring ...
  162. missing parameter documentation'''
  163. pass
  164. """)
  165. with self.assertNoMessages():
  166. self.checker.visit_functiondef(node)
  167. def test_don_t_tolerate_no_param_documentation_at_all(self):
  168. """Example of a function with no parameter documentation at all
  169. Missing documentation error message is emitted.
  170. """
  171. node = astroid.extract_node("""
  172. def function_foo(x, y):
  173. '''docstring ...
  174. missing parameter documentation'''
  175. pass
  176. """)
  177. with self.assertAddsMessages(
  178. Message(
  179. msg_id='missing-param-doc',
  180. node=node,
  181. args=('x, y',)),
  182. Message(
  183. msg_id='missing-type-doc',
  184. node=node,
  185. args=('x, y',))
  186. ):
  187. self.checker.visit_functiondef(node)
  188. def test_see_tolerate_no_param_documentation_at_all(self):
  189. """Example for the usage of "For the parameters, see"
  190. to suppress missing-param warnings.
  191. """
  192. node = astroid.extract_node("""
  193. def function_foo(x, y):
  194. '''docstring ...
  195. For the parameters, see :func:`blah`
  196. '''
  197. pass
  198. """)
  199. with self.assertNoMessages():
  200. self.checker.visit_functiondef(node)
  201. def _visit_methods_of_class(self, node):
  202. """Visit all methods of a class node
  203. :param node: class node
  204. :type node: :class:`astroid.scoped_nodes.Class`
  205. """
  206. for body_item in node.body:
  207. if (isinstance(body_item, astroid.FunctionDef)
  208. and hasattr(body_item, 'name')):
  209. self.checker.visit_functiondef(body_item)
  210. def test_missing_method_params_in_sphinx_docstring(self):
  211. """Example of a class method with missing parameter documentation in
  212. the Sphinx style docstring
  213. """
  214. node = astroid.extract_node("""
  215. class Foo(object):
  216. def method_foo(self, x, y):
  217. '''docstring ...
  218. missing parameter documentation
  219. :param x: bla
  220. '''
  221. pass
  222. """)
  223. method_node = node.body[0]
  224. with self.assertAddsMessages(
  225. Message(
  226. msg_id='missing-param-doc',
  227. node=method_node,
  228. args=('y',)),
  229. Message(
  230. msg_id='missing-type-doc',
  231. node=method_node,
  232. args=('x, y',))
  233. ):
  234. self._visit_methods_of_class(node)
  235. def test_missing_method_params_in_google_docstring(self):
  236. """Example of a class method with missing parameter documentation in
  237. the Google style docstring
  238. """
  239. node = astroid.extract_node("""
  240. class Foo(object):
  241. def method_foo(self, x, y):
  242. '''docstring ...
  243. missing parameter documentation
  244. Args:
  245. x: bla
  246. '''
  247. pass
  248. """)
  249. method_node = node.body[0]
  250. with self.assertAddsMessages(
  251. Message(
  252. msg_id='missing-param-doc',
  253. node=method_node,
  254. args=('y',)),
  255. Message(
  256. msg_id='missing-type-doc',
  257. node=method_node,
  258. args=('x, y',))
  259. ):
  260. self._visit_methods_of_class(node)
  261. def test_missing_method_params_in_numpy_docstring(self):
  262. """Example of a class method with missing parameter documentation in
  263. the Numpy style docstring
  264. """
  265. node = astroid.extract_node("""
  266. class Foo(object):
  267. def method_foo(self, x, y):
  268. '''docstring ...
  269. missing parameter documentation
  270. Parameters
  271. ----------
  272. x:
  273. bla
  274. '''
  275. pass
  276. """)
  277. method_node = node.body[0]
  278. with self.assertAddsMessages(
  279. Message(
  280. msg_id='missing-param-doc',
  281. node=method_node,
  282. args=('y',)),
  283. Message(
  284. msg_id='missing-type-doc',
  285. node=method_node,
  286. args=('x, y',))
  287. ):
  288. self._visit_methods_of_class(node)
  289. def test_existing_func_params_in_sphinx_docstring(self):
  290. """Example of a function with correctly documented parameters and
  291. return values (Sphinx style)
  292. """
  293. node = astroid.extract_node("""
  294. def function_foo(xarg, yarg, zarg, warg):
  295. '''function foo ...
  296. :param xarg: bla xarg
  297. :type xarg: int
  298. :parameter yarg: bla yarg
  299. :type yarg: my.qualified.type
  300. :arg int zarg: bla zarg
  301. :keyword my.qualified.type warg: bla warg
  302. :return: sum
  303. :rtype: float
  304. '''
  305. return xarg + yarg
  306. """)
  307. with self.assertNoMessages():
  308. self.checker.visit_functiondef(node)
  309. def test_existing_func_params_in_google_docstring(self):
  310. """Example of a function with correctly documented parameters and
  311. return values (Google style)
  312. """
  313. node = astroid.extract_node("""
  314. def function_foo(xarg, yarg, zarg, warg):
  315. '''function foo ...
  316. Args:
  317. xarg (int): bla xarg
  318. yarg (my.qualified.type): bla
  319. bla yarg
  320. zarg (int): bla zarg
  321. warg (my.qualified.type): bla warg
  322. Returns:
  323. float: sum
  324. '''
  325. return xarg + yarg
  326. """)
  327. with self.assertNoMessages():
  328. self.checker.visit_functiondef(node)
  329. def test_existing_func_params_in_numpy_docstring(self):
  330. """Example of a function with correctly documented parameters and
  331. return values (Numpy style)
  332. """
  333. node = astroid.extract_node("""
  334. def function_foo(xarg, yarg, zarg, warg):
  335. '''function foo ...
  336. Parameters
  337. ----------
  338. xarg: int
  339. bla xarg
  340. yarg: my.qualified.type
  341. bla yarg
  342. zarg: int
  343. bla zarg
  344. warg: my.qualified.type
  345. bla warg
  346. Returns
  347. -------
  348. float
  349. sum
  350. '''
  351. return xarg + yarg
  352. """)
  353. with self.assertNoMessages():
  354. self.checker.visit_functiondef(node)
  355. def test_wrong_name_of_func_params_in_sphinx_docstring(self):
  356. """Example of functions with inconsistent parameter names in the
  357. signature and in the Sphinx style documentation
  358. """
  359. node = astroid.extract_node("""
  360. def function_foo(xarg, yarg, zarg):
  361. '''function foo ...
  362. :param xarg1: bla xarg
  363. :type xarg: int
  364. :param yarg: bla yarg
  365. :type yarg1: float
  366. :param str zarg1: bla zarg
  367. '''
  368. return xarg + yarg
  369. """)
  370. with self.assertAddsMessages(
  371. Message(
  372. msg_id='missing-param-doc',
  373. node=node,
  374. args=('xarg, zarg',)),
  375. Message(
  376. msg_id='missing-type-doc',
  377. node=node,
  378. args=('yarg, zarg',)),
  379. Message(
  380. msg_id='differing-param-doc',
  381. node=node,
  382. args=('xarg1, zarg1',)),
  383. Message(
  384. msg_id='differing-type-doc',
  385. node=node,
  386. args=('yarg1, zarg1',)),
  387. ):
  388. self.checker.visit_functiondef(node)
  389. node = astroid.extract_node("""
  390. def function_foo(xarg, yarg):
  391. '''function foo ...
  392. :param yarg1: bla yarg
  393. :type yarg1: float
  394. For the other parameters, see bla.
  395. '''
  396. return xarg + yarg
  397. """)
  398. with self.assertAddsMessages(
  399. Message(
  400. msg_id='differing-param-doc',
  401. node=node,
  402. args=('yarg1',)),
  403. Message(
  404. msg_id='differing-type-doc',
  405. node=node,
  406. args=('yarg1',)),
  407. ):
  408. self.checker.visit_functiondef(node)
  409. def test_wrong_name_of_func_params_in_google_docstring(self):
  410. """Example of functions with inconsistent parameter names in the
  411. signature and in the Google style documentation
  412. """
  413. node = astroid.extract_node("""
  414. def function_foo(xarg, yarg, zarg):
  415. '''function foo ...
  416. Args:
  417. xarg1 (int): bla xarg
  418. yarg (float): bla yarg
  419. zarg1 (str): bla zarg
  420. '''
  421. return xarg + yarg
  422. """)
  423. with self.assertAddsMessages(
  424. Message(
  425. msg_id='missing-param-doc',
  426. node=node,
  427. args=('xarg, zarg',)),
  428. Message(
  429. msg_id='missing-type-doc',
  430. node=node,
  431. args=('xarg, zarg',)),
  432. Message(
  433. msg_id='differing-param-doc',
  434. node=node,
  435. args=('xarg1, zarg1',)),
  436. Message(
  437. msg_id='differing-type-doc',
  438. node=node,
  439. args=('xarg1, zarg1',)),
  440. ):
  441. self.checker.visit_functiondef(node)
  442. node = astroid.extract_node("""
  443. def function_foo(xarg, yarg):
  444. '''function foo ...
  445. Args:
  446. yarg1 (float): bla yarg
  447. For the other parameters, see bla.
  448. '''
  449. return xarg + yarg
  450. """)
  451. with self.assertAddsMessages(
  452. Message(
  453. msg_id='differing-param-doc',
  454. node=node,
  455. args=('yarg1',)),
  456. Message(
  457. msg_id='differing-type-doc',
  458. node=node,
  459. args=('yarg1',))
  460. ):
  461. self.checker.visit_functiondef(node)
  462. def test_wrong_name_of_func_params_in_numpy_docstring(self):
  463. """Example of functions with inconsistent parameter names in the
  464. signature and in the Numpy style documentation
  465. """
  466. node = astroid.extract_node("""
  467. def function_foo(xarg, yarg, zarg):
  468. '''function foo ...
  469. Parameters
  470. ----------
  471. xarg1: int
  472. bla xarg
  473. yarg: float
  474. bla yarg
  475. zarg1: str
  476. bla zarg
  477. '''
  478. return xarg + yarg
  479. """)
  480. with self.assertAddsMessages(
  481. Message(
  482. msg_id='missing-param-doc',
  483. node=node,
  484. args=('xarg, zarg',)),
  485. Message(
  486. msg_id='missing-type-doc',
  487. node=node,
  488. args=('xarg, zarg',)),
  489. Message(
  490. msg_id='differing-param-doc',
  491. node=node,
  492. args=('xarg1, zarg1',)),
  493. Message(
  494. msg_id='differing-type-doc',
  495. node=node,
  496. args=('xarg1, zarg1',)),
  497. ):
  498. self.checker.visit_functiondef(node)
  499. node = astroid.extract_node("""
  500. def function_foo(xarg, yarg):
  501. '''function foo ...
  502. Parameters
  503. ----------
  504. yarg1: float
  505. bla yarg
  506. For the other parameters, see bla.
  507. '''
  508. return xarg + yarg
  509. """)
  510. with self.assertAddsMessages(
  511. Message(
  512. msg_id='differing-param-doc',
  513. node=node,
  514. args=('yarg1',)),
  515. Message(
  516. msg_id='differing-type-doc',
  517. node=node,
  518. args=('yarg1',))
  519. ):
  520. self.checker.visit_functiondef(node)
  521. def test_see_sentence_for_func_params_in_sphinx_docstring(self):
  522. """Example for the usage of "For the other parameters, see" to avoid
  523. too many repetitions, e.g. in functions or methods adhering to a
  524. given interface (Sphinx style)
  525. """
  526. node = astroid.extract_node("""
  527. def function_foo(xarg, yarg):
  528. '''function foo ...
  529. :param yarg: bla yarg
  530. :type yarg: float
  531. For the other parameters, see :func:`bla`
  532. '''
  533. return xarg + yarg
  534. """)
  535. with self.assertNoMessages():
  536. self.checker.visit_functiondef(node)
  537. def test_see_sentence_for_func_params_in_google_docstring(self):
  538. """Example for the usage of "For the other parameters, see" to avoid
  539. too many repetitions, e.g. in functions or methods adhering to a
  540. given interface (Google style)
  541. """
  542. node = astroid.extract_node("""
  543. def function_foo(xarg, yarg):
  544. '''function foo ...
  545. Args:
  546. yarg (float): bla yarg
  547. For the other parameters, see :func:`bla`
  548. '''
  549. return xarg + yarg
  550. """)
  551. with self.assertNoMessages():
  552. self.checker.visit_functiondef(node)
  553. def test_see_sentence_for_func_params_in_numpy_docstring(self):
  554. """Example for the usage of "For the other parameters, see" to avoid
  555. too many repetitions, e.g. in functions or methods adhering to a
  556. given interface (Numpy style)
  557. """
  558. node = astroid.extract_node("""
  559. def function_foo(xarg, yarg):
  560. '''function foo ...
  561. Parameters
  562. ----------
  563. yarg: float
  564. bla yarg
  565. For the other parameters, see :func:`bla`
  566. '''
  567. return xarg + yarg
  568. """)
  569. with self.assertNoMessages():
  570. self.checker.visit_functiondef(node)
  571. def test_constr_params_in_class_sphinx(self):
  572. """Example of a class with missing constructor parameter documentation
  573. (Sphinx style)
  574. Everything is completely analogous to functions.
  575. """
  576. node = astroid.extract_node("""
  577. class ClassFoo(object):
  578. '''docstring foo
  579. :param y: bla
  580. missing constructor parameter documentation
  581. '''
  582. def __init__(self, x, y):
  583. pass
  584. """)
  585. with self.assertAddsMessages(
  586. Message(
  587. msg_id='missing-param-doc',
  588. node=node,
  589. args=('x',)),
  590. Message(
  591. msg_id='missing-type-doc',
  592. node=node,
  593. args=('x, y',))
  594. ):
  595. self._visit_methods_of_class(node)
  596. def test_constr_params_in_class_google(self):
  597. """Example of a class with missing constructor parameter documentation
  598. (Google style)
  599. Everything is completely analogous to functions.
  600. """
  601. node = astroid.extract_node("""
  602. class ClassFoo(object):
  603. '''docstring foo
  604. Args:
  605. y: bla
  606. missing constructor parameter documentation
  607. '''
  608. def __init__(self, x, y):
  609. pass
  610. """)
  611. with self.assertAddsMessages(
  612. Message(
  613. msg_id='missing-param-doc',
  614. node=node,
  615. args=('x',)),
  616. Message(
  617. msg_id='missing-type-doc',
  618. node=node,
  619. args=('x, y',))
  620. ):
  621. self._visit_methods_of_class(node)
  622. def test_constr_params_in_class_numpy(self):
  623. """Example of a class with missing constructor parameter documentation
  624. (Numpy style)
  625. Everything is completely analogous to functions.
  626. """
  627. node = astroid.extract_node("""
  628. class ClassFoo(object):
  629. '''docstring foo
  630. Parameters
  631. ----------
  632. y:
  633. bla
  634. missing constructor parameter documentation
  635. '''
  636. def __init__(self, x, y):
  637. pass
  638. """)
  639. with self.assertAddsMessages(
  640. Message(
  641. msg_id='missing-param-doc',
  642. node=node,
  643. args=('x',)),
  644. Message(
  645. msg_id='missing-type-doc',
  646. node=node,
  647. args=('x, y',))
  648. ):
  649. self._visit_methods_of_class(node)
  650. def test_constr_params_in_init_sphinx(self):
  651. """Example of a class with missing constructor parameter documentation
  652. (Sphinx style)
  653. Everything is completely analogous to functions.
  654. """
  655. node = astroid.extract_node("""
  656. class ClassFoo(object):
  657. def __init__(self, x, y):
  658. '''docstring foo constructor
  659. :param y: bla
  660. missing constructor parameter documentation
  661. '''
  662. pass
  663. """)
  664. constructor_node = node.body[0]
  665. with self.assertAddsMessages(
  666. Message(
  667. msg_id='missing-param-doc',
  668. node=constructor_node,
  669. args=('x',)),
  670. Message(
  671. msg_id='missing-type-doc',
  672. node=constructor_node,
  673. args=('x, y',))
  674. ):
  675. self._visit_methods_of_class(node)
  676. def test_constr_params_in_init_google(self):
  677. """Example of a class with missing constructor parameter documentation
  678. (Google style)
  679. Everything is completely analogous to functions.
  680. """
  681. node = astroid.extract_node("""
  682. class ClassFoo(object):
  683. def __init__(self, x, y):
  684. '''docstring foo constructor
  685. Args:
  686. y: bla
  687. missing constructor parameter documentation
  688. '''
  689. pass
  690. """)
  691. constructor_node = node.body[0]
  692. with self.assertAddsMessages(
  693. Message(
  694. msg_id='missing-param-doc',
  695. node=constructor_node,
  696. args=('x',)),
  697. Message(
  698. msg_id='missing-type-doc',
  699. node=constructor_node,
  700. args=('x, y',))
  701. ):
  702. self._visit_methods_of_class(node)
  703. def test_constr_params_in_init_numpy(self):
  704. """Example of a class with missing constructor parameter documentation
  705. (Numpy style)
  706. Everything is completely analogous to functions.
  707. """
  708. node = astroid.extract_node("""
  709. class ClassFoo(object):
  710. def __init__(self, x, y):
  711. '''docstring foo constructor
  712. Parameters
  713. ----------
  714. y:
  715. bla
  716. missing constructor parameter documentation
  717. '''
  718. pass
  719. """)
  720. constructor_node = node.body[0]
  721. with self.assertAddsMessages(
  722. Message(
  723. msg_id='missing-param-doc',
  724. node=constructor_node,
  725. args=('x',)),
  726. Message(
  727. msg_id='missing-type-doc',
  728. node=constructor_node,
  729. args=('x, y',))
  730. ):
  731. self._visit_methods_of_class(node)
  732. def test_see_sentence_for_constr_params_in_class(self):
  733. """Example usage of "For the parameters, see" in class docstring"""
  734. node = astroid.extract_node("""
  735. class ClassFoo(object):
  736. '''docstring foo
  737. For the parameters, see :func:`bla`
  738. '''
  739. def __init__(self, x, y):
  740. '''init'''
  741. pass
  742. """)
  743. with self.assertNoMessages():
  744. self._visit_methods_of_class(node)
  745. def test_see_sentence_for_constr_params_in_init(self):
  746. """Example usage of "For the parameters, see" in init docstring"""
  747. node = astroid.extract_node("""
  748. class ClassFoo(object):
  749. '''foo'''
  750. def __init__(self, x, y):
  751. '''docstring foo constructor
  752. For the parameters, see :func:`bla`
  753. '''
  754. pass
  755. """)
  756. with self.assertNoMessages():
  757. self._visit_methods_of_class(node)
  758. def test_constr_params_in_class_and_init_sphinx(self):
  759. """Example of a class with missing constructor parameter documentation
  760. in both the init docstring and the class docstring
  761. (Sphinx style)
  762. Everything is completely analogous to functions.
  763. """
  764. node = astroid.extract_node("""
  765. class ClassFoo(object):
  766. '''docstring foo
  767. :param y: None
  768. missing constructor parameter documentation
  769. '''
  770. def __init__(self, x, y):
  771. '''docstring foo
  772. :param y: bla
  773. missing constructor parameter documentation
  774. '''
  775. pass
  776. """)
  777. constructor_node = node.body[0]
  778. with self.assertAddsMessages(
  779. Message(
  780. msg_id='multiple-constructor-doc',
  781. node=node,
  782. args=(node.name,)),
  783. Message(
  784. msg_id='missing-param-doc',
  785. node=node,
  786. args=('x',)),
  787. Message(
  788. msg_id='missing-type-doc',
  789. node=node,
  790. args=('x, y',)),
  791. Message(
  792. msg_id='missing-param-doc',
  793. node=constructor_node,
  794. args=('x',)),
  795. Message(
  796. msg_id='missing-type-doc',
  797. node=constructor_node,
  798. args=('x, y',)),
  799. ):
  800. self._visit_methods_of_class(node)
  801. def test_constr_params_in_class_and_init_google(self):
  802. """Example of a class with missing constructor parameter documentation
  803. in both the init docstring and the class docstring
  804. (Google style)
  805. Everything is completely analogous to functions.
  806. """
  807. node = astroid.extract_node("""
  808. class ClassFoo(object):
  809. '''docstring foo
  810. Args:
  811. y: bla
  812. missing constructor parameter documentation
  813. '''
  814. def __init__(self, x, y):
  815. '''docstring foo
  816. Args:
  817. y: bla
  818. missing constructor parameter documentation
  819. '''
  820. pass
  821. """)
  822. constructor_node = node.body[0]
  823. with self.assertAddsMessages(
  824. Message(
  825. msg_id='multiple-constructor-doc',
  826. node=node,
  827. args=(node.name,)),
  828. Message(
  829. msg_id='missing-param-doc',
  830. node=node,
  831. args=('x',)),
  832. Message(
  833. msg_id='missing-type-doc',
  834. node=node,
  835. args=('x, y',)),
  836. Message(
  837. msg_id='missing-param-doc',
  838. node=constructor_node,
  839. args=('x',)),
  840. Message(
  841. msg_id='missing-type-doc',
  842. node=constructor_node,
  843. args=('x, y',)),
  844. ):
  845. self._visit_methods_of_class(node)
  846. def test_constr_params_in_class_and_init_numpy(self):
  847. """Example of a class with missing constructor parameter documentation
  848. in both the init docstring and the class docstring
  849. (Numpy style)
  850. Everything is completely analogous to functions.
  851. """
  852. node = astroid.extract_node("""
  853. class ClassFoo(object):
  854. '''docstring foo
  855. Parameters
  856. ----------
  857. y:
  858. bla
  859. missing constructor parameter documentation
  860. '''
  861. def __init__(self, x, y):
  862. '''docstring foo
  863. Parameters
  864. ----------
  865. y:
  866. bla
  867. missing constructor parameter documentation
  868. '''
  869. pass
  870. """)
  871. constructor_node = node.body[0]
  872. with self.assertAddsMessages(
  873. Message(
  874. msg_id='multiple-constructor-doc',
  875. node=node,
  876. args=(node.name,)),
  877. Message(
  878. msg_id='missing-param-doc',
  879. node=node,
  880. args=('x',)),
  881. Message(
  882. msg_id='missing-type-doc',
  883. node=node,
  884. args=('x, y',)),
  885. Message(
  886. msg_id='missing-param-doc',
  887. node=constructor_node,
  888. args=('x',)),
  889. Message(
  890. msg_id='missing-type-doc',
  891. node=constructor_node,
  892. args=('x, y',)),
  893. ):
  894. self._visit_methods_of_class(node)
  895. @pytest.mark.skipif(sys.version_info[0] != 3, reason="Enabled on Python 3")
  896. def test_kwonlyargs_are_taken_in_account(self):
  897. node = astroid.extract_node('''
  898. def my_func(arg, *, kwonly, missing_kwonly):
  899. """The docstring
  900. :param int arg: The argument.
  901. :param bool kwonly: A keyword-arg.
  902. """
  903. ''')
  904. with self.assertAddsMessages(
  905. Message(
  906. msg_id='missing-param-doc',
  907. node=node,
  908. args=('missing_kwonly', )),
  909. Message(
  910. msg_id='missing-type-doc',
  911. node=node,
  912. args=('missing_kwonly', ))):
  913. self.checker.visit_functiondef(node)
  914. def test_warns_missing_args_sphinx(self):
  915. node = astroid.extract_node('''
  916. def my_func(named_arg, *args):
  917. """The docstring
  918. :param named_arg: Returned
  919. :type named_arg: object
  920. :returns: Maybe named_arg
  921. :rtype: object or None
  922. """
  923. if args:
  924. return named_arg
  925. ''')
  926. with self.assertAddsMessages(
  927. Message(
  928. msg_id='missing-param-doc',
  929. node=node,
  930. args=('args',))):
  931. self.checker.visit_functiondef(node)
  932. def test_warns_missing_kwargs_sphinx(self):
  933. node = astroid.extract_node('''
  934. def my_func(named_arg, **kwargs):
  935. """The docstring
  936. :param named_arg: Returned
  937. :type named_arg: object
  938. :returns: Maybe named_arg
  939. :rtype: object or None
  940. """
  941. if kwargs:
  942. return named_arg
  943. ''')
  944. with self.assertAddsMessages(
  945. Message(
  946. msg_id='missing-param-doc',
  947. node=node,
  948. args=('kwargs',))):
  949. self.checker.visit_functiondef(node)
  950. def test_warns_missing_args_google(self):
  951. node = astroid.extract_node('''
  952. def my_func(named_arg, *args):
  953. """The docstring
  954. Args:
  955. named_arg (object): Returned
  956. Returns:
  957. object or None: Maybe named_arg
  958. """
  959. if args:
  960. return named_arg
  961. ''')
  962. with self.assertAddsMessages(
  963. Message(
  964. msg_id='missing-param-doc',
  965. node=node,
  966. args=('args',))):
  967. self.checker.visit_functiondef(node)
  968. def test_warns_missing_kwargs_google(self):
  969. node = astroid.extract_node('''
  970. def my_func(named_arg, **kwargs):
  971. """The docstring
  972. Args:
  973. named_arg (object): Returned
  974. Returns:
  975. object or None: Maybe named_arg
  976. """
  977. if kwargs:
  978. return named_arg
  979. ''')
  980. with self.assertAddsMessages(
  981. Message(
  982. msg_id='missing-param-doc',
  983. node=node,
  984. args=('kwargs',))):
  985. self.checker.visit_functiondef(node)
  986. def test_warns_missing_args_numpy(self):
  987. node = astroid.extract_node('''
  988. def my_func(named_arg, *args):
  989. """The docstring
  990. Args
  991. ----
  992. named_arg : object
  993. Returned
  994. Returns
  995. -------
  996. object or None
  997. Maybe named_arg
  998. """
  999. if args:
  1000. return named_arg
  1001. ''')
  1002. with self.assertAddsMessages(
  1003. Message(
  1004. msg_id='missing-param-doc',
  1005. node=node,
  1006. args=('args',))):
  1007. self.checker.visit_functiondef(node)
  1008. def test_warns_missing_kwargs_numpy(self):
  1009. node = astroid.extract_node('''
  1010. def my_func(named_arg, **kwargs):
  1011. """The docstring
  1012. Args
  1013. ----
  1014. named_arg : object
  1015. Returned
  1016. Returns
  1017. -------
  1018. object or None
  1019. Maybe named_arg
  1020. """
  1021. if kwargs:
  1022. return named_arg
  1023. ''')
  1024. with self.assertAddsMessages(
  1025. Message(
  1026. msg_id='missing-param-doc',
  1027. node=node,
  1028. args=('kwargs',))):
  1029. self.checker.visit_functiondef(node)
  1030. def test_finds_args_without_type_sphinx(self):
  1031. node = astroid.extract_node('''
  1032. def my_func(named_arg, *args):
  1033. """The docstring
  1034. :param named_arg: Returned
  1035. :type named_arg: object
  1036. :param args: Optional arguments
  1037. :returns: Maybe named_arg
  1038. :rtype: object or None
  1039. """
  1040. if args:
  1041. return named_arg
  1042. ''')
  1043. with self.assertNoMessages():
  1044. self.checker.visit_functiondef(node)
  1045. def test_finds_kwargs_without_type_sphinx(self):
  1046. node = astroid.extract_node('''
  1047. def my_func(named_arg, **kwargs):
  1048. """The docstring
  1049. :param named_arg: Returned
  1050. :type named_arg: object
  1051. :param kwargs: Keyword arguments
  1052. :returns: Maybe named_arg
  1053. :rtype: object or None
  1054. """
  1055. if kwargs:
  1056. return named_arg
  1057. ''')
  1058. with self.assertNoMessages():
  1059. self.checker.visit_functiondef(node)
  1060. def test_finds_args_without_type_google(self):
  1061. node = astroid.extract_node('''
  1062. def my_func(named_arg, *args):
  1063. """The docstring
  1064. Args:
  1065. named_arg (object): Returned
  1066. *args: Optional arguments
  1067. Returns:
  1068. object or None: Maybe named_arg
  1069. """
  1070. if args:
  1071. return named_arg
  1072. ''')
  1073. with self.assertNoMessages():
  1074. self.checker.visit_functiondef(node)
  1075. def test_finds_kwargs_without_type_google(self):
  1076. node = astroid.extract_node('''
  1077. def my_func(named_arg, **kwargs):
  1078. """The docstring
  1079. Args:
  1080. named_arg (object): Returned
  1081. **kwargs: Keyword arguments
  1082. Returns:
  1083. object or None: Maybe named_arg
  1084. """
  1085. if kwargs:
  1086. return named_arg
  1087. ''')
  1088. with self.assertNoMessages():
  1089. self.checker.visit_functiondef(node)
  1090. def test_finds_args_without_type_numpy(self):
  1091. node = astroid.extract_node('''
  1092. def my_func(named_arg, *args):
  1093. """The docstring
  1094. Args
  1095. ----
  1096. named_arg : object
  1097. Returned
  1098. args :
  1099. Optional Arguments
  1100. Returns
  1101. -------
  1102. object or None
  1103. Maybe named_arg
  1104. """
  1105. if args:
  1106. return named_arg
  1107. ''')
  1108. with self.assertNoMessages():
  1109. self.checker.visit_functiondef(node)
  1110. def test_finds_args_with_xref_type_google(self):
  1111. node = astroid.extract_node('''
  1112. def my_func(named_arg, **kwargs):
  1113. """The docstring
  1114. Args:
  1115. named_arg (`example.value`): Returned
  1116. **kwargs: Keyword arguments
  1117. Returns:
  1118. `example.value`: Maybe named_arg
  1119. """
  1120. if kwargs:
  1121. return named_arg
  1122. ''')
  1123. with self.assertNoMessages():
  1124. self.checker.visit_functiondef(node)
  1125. def test_finds_args_with_xref_type_numpy(self):
  1126. node = astroid.extract_node('''
  1127. def my_func(named_arg, *args):
  1128. """The docstring
  1129. Args
  1130. ----
  1131. named_arg : `example.value`
  1132. Returned
  1133. args :
  1134. Optional Arguments
  1135. Returns
  1136. -------
  1137. `example.value`
  1138. Maybe named_arg
  1139. """
  1140. if args:
  1141. return named_arg
  1142. ''')
  1143. with self.assertNoMessages():
  1144. self.checker.visit_functiondef(node)
  1145. def test_finds_kwargs_without_type_numpy(self):
  1146. node = astroid.extract_node('''
  1147. def my_func(named_arg, **kwargs):
  1148. """The docstring
  1149. Args
  1150. ----
  1151. named_arg : object
  1152. Returned
  1153. kwargs :
  1154. Keyword arguments
  1155. Returns
  1156. -------
  1157. object or None
  1158. Maybe named_arg
  1159. """
  1160. if kwargs:
  1161. return named_arg
  1162. ''')
  1163. with self.assertNoMessages():
  1164. self.checker.visit_functiondef(node)
  1165. CONTAINER_TYPES = [
  1166. 'dict(str,str)',
  1167. 'dict[str,str]',
  1168. 'tuple(int)',
  1169. 'list[tokenize.TokenInfo]',
  1170. ]
  1171. COMPLEX_TYPES = CONTAINER_TYPES + [
  1172. 'dict(str, str)',
  1173. 'dict[str, str]',
  1174. 'int or str',
  1175. 'tuple(int or str)',
  1176. 'tuple(int) or list(int)',
  1177. 'tuple(int or str) or list(int or str)',
  1178. ]
  1179. @pytest.mark.parametrize('complex_type', COMPLEX_TYPES)
  1180. def test_finds_multiple_types_sphinx(self, complex_type):
  1181. node = astroid.extract_node('''
  1182. def my_func(named_arg):
  1183. """The docstring
  1184. :param named_arg: Returned
  1185. :type named_arg: {0}
  1186. :returns: named_arg
  1187. :rtype: {0}
  1188. """
  1189. return named_arg
  1190. '''.format(complex_type))
  1191. with self.assertNoMessages():
  1192. self.checker.visit_functiondef(node)
  1193. @pytest.mark.parametrize('complex_type', COMPLEX_TYPES)
  1194. def test_finds_multiple_types_google(self, complex_type):
  1195. node = astroid.extract_node('''
  1196. def my_func(named_arg):
  1197. """The docstring
  1198. Args:
  1199. named_arg ({0}): Returned
  1200. Returns:
  1201. {0}: named_arg
  1202. """
  1203. return named_arg
  1204. '''.format(complex_type))
  1205. with self.assertNoMessages():
  1206. self.checker.visit_functiondef(node)
  1207. @pytest.mark.parametrize('complex_type', COMPLEX_TYPES)
  1208. def test_finds_multiple_types_numpy(self, complex_type):
  1209. node = astroid.extract_node('''
  1210. def my_func(named_arg):
  1211. """The docstring
  1212. Args
  1213. ----
  1214. named_arg : {0}
  1215. Returned
  1216. Returns
  1217. -------
  1218. {0}
  1219. named_arg
  1220. """
  1221. return named_arg
  1222. '''.format(complex_type))
  1223. with self.assertNoMessages():
  1224. self.checker.visit_functiondef(node)
  1225. @pytest.mark.parametrize('container_type', CONTAINER_TYPES)
  1226. def test_finds_compact_container_types_sphinx(self, container_type):
  1227. node = astroid.extract_node('''
  1228. def my_func(named_arg):
  1229. """The docstring
  1230. :param {0} named_arg: Returned
  1231. :returns: named_arg
  1232. :rtype: {0}
  1233. """
  1234. return named_arg
  1235. '''.format(container_type))
  1236. with self.assertNoMessages():
  1237. self.checker.visit_functiondef(node)
  1238. def test_ignores_optional_specifier_numpy(self):
  1239. node = astroid.extract_node('''
  1240. def do_something(param, param2='all'):
  1241. """Do something.
  1242. Parameters
  1243. ----------
  1244. param : str
  1245. Description.
  1246. param2 : str, optional
  1247. Description (the default is 'all').
  1248. Returns
  1249. -------
  1250. int
  1251. Description.
  1252. """
  1253. return param, param2
  1254. ''')
  1255. with self.assertNoMessages():
  1256. self.checker.visit_functiondef(node)
  1257. def test_finds_short_name_exception(self):
  1258. node = astroid.extract_node('''
  1259. from fake_package import BadError
  1260. def do_something(): #@
  1261. """Do something.
  1262. Raises:
  1263. ~fake_package.exceptions.BadError: When something bad happened.
  1264. """
  1265. raise BadError("A bad thing happened.")
  1266. ''')
  1267. with self.assertNoMessages():
  1268. self.checker.visit_functiondef(node)
  1269. def test_finds_missing_raises_from_setter_sphinx(self):
  1270. """Example of a setter having missing raises documentation in
  1271. the Sphinx style docstring of the property
  1272. """
  1273. property_node, node = astroid.extract_node("""
  1274. class Foo(object):
  1275. @property
  1276. def foo(self): #@
  1277. '''docstring ...
  1278. :type: int
  1279. '''
  1280. return 10
  1281. @foo.setter
  1282. def foo(self, value):
  1283. raise AttributeError() #@
  1284. """)
  1285. with self.assertAddsMessages(
  1286. Message(
  1287. msg_id='missing-raises-doc',
  1288. node=property_node,
  1289. args=('AttributeError',)),
  1290. ):
  1291. self.checker.visit_raise(node)
  1292. def test_finds_missing_raises_from_setter_google(self):
  1293. """Example of a setter having missing raises documentation in
  1294. the Google style docstring of the property
  1295. """
  1296. property_node, node = astroid.extract_node("""
  1297. class Foo(object):
  1298. @property
  1299. def foo(self): #@
  1300. '''int: docstring
  1301. Include a "Raises" section so that this is identified
  1302. as a Google docstring and not a Numpy docstring.
  1303. Raises:
  1304. RuntimeError: Always
  1305. '''
  1306. raise RuntimeError()
  1307. return 10
  1308. @foo.setter
  1309. def foo(self, value):
  1310. raises AttributeError() #@
  1311. """)
  1312. with self.assertAddsMessages(
  1313. Message(
  1314. msg_id='missing-raises-doc',
  1315. node=property_node,
  1316. args=('AttributeError',)),
  1317. ):
  1318. self.checker.visit_raise(node)
  1319. def test_finds_missing_raises_from_setter_numpy(self):
  1320. """Example of a setter having missing raises documentation in
  1321. the Numpy style docstring of the property
  1322. """
  1323. property_node, node = astroid.extract_node("""
  1324. class Foo(object):
  1325. @property
  1326. def foo(self): #@
  1327. '''int: docstring
  1328. Include a "Raises" section so that this is identified
  1329. as a Numpy docstring and not a Google docstring.
  1330. Raises
  1331. ------
  1332. RuntimeError
  1333. Always
  1334. '''
  1335. raise RuntimeError()
  1336. return 10
  1337. @foo.setter
  1338. def foo(self, value):
  1339. raises AttributeError() #@
  1340. """)
  1341. with self.assertAddsMessages(
  1342. Message(
  1343. msg_id='missing-raises-doc',
  1344. node=property_node,
  1345. args=('AttributeError',)),
  1346. ):
  1347. self.checker.visit_raise(node)
  1348. def test_finds_missing_raises_in_setter_sphinx(self):
  1349. """Example of a setter having missing raises documentation in
  1350. its own Sphinx style docstring
  1351. """
  1352. setter_node, node = astroid.extract_node("""
  1353. class Foo(object):
  1354. @property
  1355. def foo(self):
  1356. '''docstring ...
  1357. :type: int
  1358. :raises RuntimeError: Always
  1359. '''
  1360. raise RuntimeError()
  1361. return 10
  1362. @foo.setter
  1363. def foo(self, value): #@
  1364. '''setter docstring ...
  1365. :type: None
  1366. '''
  1367. raise AttributeError() #@
  1368. """)
  1369. with self.assertAddsMessages(
  1370. Message(
  1371. msg_id='missing-raises-doc',
  1372. node=setter_node,
  1373. args=('AttributeError',)),
  1374. ):
  1375. self.checker.visit_raise(node)
  1376. def test_finds_missing_raises_from_setter_google(self):
  1377. """Example of a setter having missing raises documentation in
  1378. its own Google style docstring of the property
  1379. """
  1380. setter_node, node = astroid.extract_node("""
  1381. class Foo(object):
  1382. @property
  1383. def foo(self):
  1384. '''int: docstring ...
  1385. Raises:
  1386. RuntimeError: Always
  1387. '''
  1388. raise RuntimeError()
  1389. return 10
  1390. @foo.setter
  1391. def foo(self, value): #@
  1392. '''setter docstring ...
  1393. Raises:
  1394. RuntimeError: Never
  1395. '''
  1396. if True:
  1397. raise AttributeError() #@
  1398. raise RuntimeError()
  1399. """)
  1400. with self.assertAddsMessages(
  1401. Message(
  1402. msg_id='missing-raises-doc',
  1403. node=setter_node,
  1404. args=('AttributeError',)),
  1405. ):
  1406. self.checker.visit_raise(node)
  1407. def test_finds_missing_raises_from_setter_numpy(self):
  1408. """Example of a setter having missing raises documentation in
  1409. its own Numpy style docstring of the property
  1410. """
  1411. setter_node, node = astroid.extract_node("""
  1412. class Foo(object):
  1413. @property
  1414. def foo(self):
  1415. '''int: docstring ...
  1416. Raises
  1417. ------
  1418. RuntimeError
  1419. Always
  1420. '''
  1421. raise RuntimeError()
  1422. return 10
  1423. @foo.setter
  1424. def foo(self, value): #@
  1425. '''setter docstring ...
  1426. Raises
  1427. ------
  1428. RuntimeError
  1429. Never
  1430. '''
  1431. if True:
  1432. raise AttributeError() #@
  1433. raise RuntimeError()
  1434. """)
  1435. with self.assertAddsMessages(
  1436. Message(
  1437. msg_id='missing-raises-doc',
  1438. node=setter_node,
  1439. args=('AttributeError',)),
  1440. ):
  1441. self.checker.visit_raise(node)
  1442. def test_finds_property_return_type_sphinx(self):
  1443. """Example of a property having return documentation in
  1444. a Sphinx style docstring
  1445. """
  1446. node = astroid.extract_node("""
  1447. class Foo(object):
  1448. @property
  1449. def foo(self): #@
  1450. '''docstring ...
  1451. :type: int
  1452. '''
  1453. return 10
  1454. """)
  1455. with self.assertNoMessages():
  1456. self.checker.visit_functiondef(node)
  1457. def test_finds_property_return_type_google(self):
  1458. """Example of a property having return documentation in
  1459. a Google style docstring
  1460. """
  1461. node = astroid.extract_node("""
  1462. class Foo(object):
  1463. @property
  1464. def foo(self): #@
  1465. '''int: docstring ...
  1466. Raises:
  1467. RuntimeError: Always
  1468. '''
  1469. raise RuntimeError()
  1470. return 10
  1471. """)
  1472. with self.assertNoMessages():
  1473. self.checker.visit_functiondef(node)
  1474. def test_finds_property_return_type_numpy(self):
  1475. """Example of a property having return documentation in
  1476. a numpy style docstring
  1477. """
  1478. node = astroid.extract_node("""
  1479. class Foo(object):
  1480. @property
  1481. def foo(self): #@
  1482. '''int: docstring ...
  1483. Raises
  1484. ------
  1485. RuntimeError
  1486. Always
  1487. '''
  1488. raise RuntimeError()
  1489. return 10
  1490. """)
  1491. with self.assertNoMessages():
  1492. self.checker.visit_functiondef(node)
  1493. def test_finds_missing_property_return_type_sphinx(self):
  1494. """Example of a property having missing return documentation in
  1495. a Sphinx style docstring
  1496. """
  1497. property_node, node = astroid.extract_node("""
  1498. class Foo(object):
  1499. @property
  1500. def foo(self): #@
  1501. '''docstring ...
  1502. :raises RuntimeError: Always
  1503. '''
  1504. raise RuntimeError()
  1505. return 10 #@
  1506. """)
  1507. with self.assertAddsMessages(
  1508. Message(
  1509. msg_id='missing-return-type-doc',
  1510. node=property_node),
  1511. ):
  1512. self.checker.visit_return(node)
  1513. def test_finds_missing_property_return_type_google(self):
  1514. """Example of a property having return documentation in
  1515. a Google style docstring
  1516. """
  1517. property_node, node = astroid.extract_node("""
  1518. class Foo(object):
  1519. @property
  1520. def foo(self): #@
  1521. '''docstring ...
  1522. Raises:
  1523. RuntimeError: Always
  1524. '''
  1525. raise RuntimeError()
  1526. return 10 #@
  1527. """)
  1528. with self.assertAddsMessages(
  1529. Message(
  1530. msg_id='missing-return-type-doc',
  1531. node=property_node),
  1532. ):
  1533. self.checker.visit_return(node)
  1534. def test_finds_missing_property_return_type_numpy(self):
  1535. """Example of a property having return documentation in
  1536. a numpy style docstring
  1537. """
  1538. property_node, node = astroid.extract_node("""
  1539. class Foo(object):
  1540. @property
  1541. def foo(self): #@
  1542. '''docstring ...
  1543. Raises
  1544. ------
  1545. RuntimeError
  1546. Always
  1547. '''
  1548. raise RuntimeError()
  1549. return 10 #@
  1550. """)
  1551. with self.assertAddsMessages(
  1552. Message(
  1553. msg_id='missing-return-type-doc',
  1554. node=property_node),
  1555. ):
  1556. self.checker.visit_return(node)
  1557. def test_ignores_non_property_return_type_sphinx(self):
  1558. """Example of a class function trying to use `type` as return
  1559. documentation in a Sphinx style docstring
  1560. """
  1561. func_node, node = astroid.extract_node("""
  1562. class Foo(object):
  1563. def foo(self): #@
  1564. '''docstring ...
  1565. :type: int
  1566. '''
  1567. return 10 #@
  1568. """)
  1569. with self.assertAddsMessages(
  1570. Message(
  1571. msg_id='missing-return-doc',
  1572. node=func_node),
  1573. Message(
  1574. msg_id='missing-return-type-doc',
  1575. node=func_node),
  1576. ):
  1577. self.checker.visit_return(node)
  1578. def test_ignores_non_property_return_type_google(self):
  1579. """Example of a class function trying to use `type` as return
  1580. documentation in a Google style docstring
  1581. """
  1582. func_node, node = astroid.extract_node("""
  1583. class Foo(object):
  1584. def foo(self): #@
  1585. '''int: docstring ...
  1586. Raises:
  1587. RuntimeError: Always
  1588. '''
  1589. raise RuntimeError()
  1590. return 10 #@
  1591. """)
  1592. with self.assertAddsMessages(
  1593. Message(
  1594. msg_id='missing-return-doc',
  1595. node=func_node),
  1596. Message(
  1597. msg_id='missing-return-type-doc',
  1598. node=func_node),
  1599. ):
  1600. self.checker.visit_return(node)
  1601. def test_ignores_non_property_return_type_numpy(self):
  1602. """Example of a class function trying to use `type` as return
  1603. documentation in a numpy style docstring
  1604. """
  1605. func_node, node = astroid.extract_node("""
  1606. class Foo(object):
  1607. def foo(self): #@
  1608. '''int: docstring ...
  1609. Raises
  1610. ------
  1611. RuntimeError
  1612. Always
  1613. '''
  1614. raise RuntimeError()
  1615. return 10 #@
  1616. """)
  1617. with self.assertAddsMessages(
  1618. Message(
  1619. msg_id='missing-return-doc',
  1620. node=func_node),
  1621. Message(
  1622. msg_id='missing-return-type-doc',
  1623. node=func_node),
  1624. ):
  1625. self.checker.visit_return(node)
  1626. def test_ignores_return_in_abstract_method_sphinx(self):
  1627. """Example of an abstract method documenting the return type that an
  1628. implementation should return.
  1629. """
  1630. node = astroid.extract_node("""
  1631. import abc
  1632. class Foo(object):
  1633. @abc.abstractmethod
  1634. def foo(self): #@
  1635. '''docstring ...
  1636. :returns: Ten
  1637. :rtype: int
  1638. '''
  1639. return 10
  1640. """)
  1641. with self.assertNoMessages():
  1642. self.checker.visit_functiondef(node)
  1643. def test_ignores_return_in_abstract_method_google(self):
  1644. """Example of an abstract method documenting the return type that an
  1645. implementation should return.
  1646. """
  1647. node = astroid.extract_node("""
  1648. import abc
  1649. class Foo(object):
  1650. @abc.abstractmethod
  1651. def foo(self): #@
  1652. '''docstring ...
  1653. Returns:
  1654. int: Ten
  1655. '''
  1656. return 10
  1657. """)
  1658. with self.assertNoMessages():
  1659. self.checker.visit_functiondef(node)
  1660. def test_ignores_return_in_abstract_method_numpy(self):
  1661. """Example of an abstract method documenting the return type that an
  1662. implementation should return.
  1663. """
  1664. node = astroid.extract_node("""
  1665. import abc
  1666. class Foo(object):
  1667. @abc.abstractmethod
  1668. def foo(self): #@
  1669. '''docstring ...
  1670. Returns
  1671. -------
  1672. int
  1673. Ten
  1674. '''
  1675. return 10
  1676. """)
  1677. with self.assertNoMessages():
  1678. self.checker.visit_functiondef(node)
  1679. def test_ignores_raise_notimplementederror_sphinx(self):
  1680. """Example of an abstract
  1681. """
  1682. node = astroid.extract_node("""
  1683. class Foo(object):
  1684. def foo(self, arg): #@
  1685. '''docstring ...
  1686. :param arg: An argument.
  1687. :type arg: int
  1688. '''
  1689. raise NotImplementedError()
  1690. """)
  1691. with self.assertNoMessages():
  1692. self.checker.visit_functiondef(node)
  1693. def test_ignores_return_in_abstract_method_google(self):
  1694. """Example of a method documenting the return type that an
  1695. implementation should return.
  1696. """
  1697. node = astroid.extract_node("""
  1698. class Foo(object):
  1699. def foo(self, arg): #@
  1700. '''docstring ...
  1701. Args:
  1702. arg (int): An argument.
  1703. '''
  1704. raise NotImplementedError()
  1705. """)
  1706. with self.assertNoMessages():
  1707. self.checker.visit_functiondef(node)
  1708. def test_ignores_return_in_abstract_method_numpy(self):
  1709. """Example of a method documenting the return type that an
  1710. implementation should return.
  1711. """
  1712. node = astroid.extract_node("""
  1713. class Foo(object):
  1714. def foo(self, arg): #@
  1715. '''docstring ...
  1716. Parameters
  1717. ----------
  1718. arg : int
  1719. An argument.
  1720. '''
  1721. raise NotImplementedError()
  1722. """)
  1723. with self.assertNoMessages():
  1724. self.checker.visit_functiondef(node)