Coverage for tests/test_docstrings/test_google.py: 100.00%

515 statements  

« prev     ^ index     » next       coverage.py v7.6.2, created at 2024-10-12 01:34 +0200

1"""Tests for the [Google-style parser][griffe.docstrings.google].""" 

2 

3from __future__ import annotations 

4 

5import inspect 

6from typing import TYPE_CHECKING 

7 

8import pytest 

9 

10from griffe import ( 

11 Attribute, 

12 Class, 

13 Docstring, 

14 DocstringReceive, 

15 DocstringReturn, 

16 DocstringSectionKind, 

17 DocstringYield, 

18 ExprName, 

19 Function, 

20 Module, 

21 Parameter, 

22 Parameters, 

23 parse_docstring_annotation, 

24) 

25 

26if TYPE_CHECKING: 

27 from tests.test_docstrings.helpers import ParserType 

28 

29 

30# ============================================================================================= 

31# Markup flow (multilines, indentation, etc.) 

32def test_simple_docstring(parse_google: ParserType) -> None: 

33 """Parse a simple docstring. 

34 

35 Parameters: 

36 parse_google: Fixture parser. 

37 """ 

38 sections, warnings = parse_google("A simple docstring.") 

39 assert len(sections) == 1 

40 assert not warnings 

41 

42 

43def test_multiline_docstring(parse_google: ParserType) -> None: 

44 """Parse a multi-line docstring. 

45 

46 Parameters: 

47 parse_google: Fixture parser. 

48 """ 

49 sections, warnings = parse_google( 

50 """ 

51 A somewhat longer docstring. 

52 

53 Blablablabla. 

54 """, 

55 ) 

56 assert len(sections) == 1 

57 assert not warnings 

58 

59 

60def test_parse_partially_indented_lines(parse_google: ParserType) -> None: 

61 """Properly handle partially indented lines. 

62 

63 Parameters: 

64 parse_google: Fixture parser. 

65 """ 

66 docstring = """ 

67 The available formats are: 

68 - JSON 

69 

70 The unavailable formats are: 

71 - YAML 

72 """ 

73 sections, warnings = parse_google(docstring) 

74 assert len(sections) == 2 

75 assert sections[0].kind is DocstringSectionKind.admonition 

76 assert sections[1].kind is DocstringSectionKind.admonition 

77 assert not warnings 

78 

79 

80def test_multiple_lines_in_sections_items(parse_google: ParserType) -> None: 

81 """Parse multi-line item description. 

82 

83 Parameters: 

84 parse_google: Fixture parser. 

85 """ 

86 docstring = """ 

87 Parameters: 

88 p (int): This parameter 

89 has a description 

90 spawning on multiple lines. 

91 

92 It even has blank lines in it. 

93 Some of these lines 

94 are indented for no reason. 

95 q (int): 

96 What if the first line is blank? 

97 """ 

98 

99 sections, warnings = parse_google(docstring) 

100 assert len(sections) == 1 

101 assert len(sections[0].value) == 2 

102 assert warnings 

103 for warning in warnings: 

104 assert "should be 4 * 2 = 8 spaces, not" in warning 

105 

106 

107def test_code_blocks(parse_google: ParserType) -> None: 

108 """Parse code blocks. 

109 

110 Parameters: 

111 parse_google: Fixture parser. 

112 """ 

113 docstring = """ 

114 This docstring contains a code block! 

115 

116 ```python 

117 print("hello") 

118 ``` 

119 """ 

120 

121 sections, warnings = parse_google(docstring) 

122 assert len(sections) == 1 

123 assert not warnings 

124 

125 

126def test_indented_code_block(parse_google: ParserType) -> None: 

127 """Parse indented code blocks. 

128 

129 Parameters: 

130 parse_google: Fixture parser. 

131 """ 

132 docstring = """ 

133 This docstring contains a docstring in a code block o_O! 

134 

135 \"\"\" 

136 This docstring is contained in another docstring O_o! 

137 

138 Parameters: 

139 s: A string. 

140 \"\"\" 

141 """ 

142 

143 sections, warnings = parse_google(docstring) 

144 assert len(sections) == 1 

145 assert not warnings 

146 

147 

148def test_different_indentation(parse_google: ParserType) -> None: 

149 """Parse different indentations, warn on confusing indentation. 

150 

151 Parameters: 

152 parse_google: Fixture parser. 

153 """ 

154 docstring = """ 

155 Raises: 

156 StartAt5: this section's items starts with 5 spaces of indentation. 

157 Well indented continuation line. 

158 Badly indented continuation line (will trigger a warning). 

159 

160 Empty lines are preserved, as well as extra-indentation (this line is a code block). 

161 AnyOtherLine: ...starting with exactly 5 spaces is a new item. 

162 AnyLine: ...indented with less than 5 spaces signifies the end of the section. 

163 """ 

164 

165 sections, warnings = parse_google(docstring) 

166 assert len(sections) == 2 

167 assert len(sections[0].value) == 2 

168 assert sections[0].value[0].description == ( 

169 "this section's items starts with 5 spaces of indentation.\n" 

170 "Well indented continuation line.\n" 

171 "Badly indented continuation line (will trigger a warning).\n" 

172 "\n" 

173 " Empty lines are preserved, as well as extra-indentation (this line is a code block)." 

174 ) 

175 assert sections[1].value == " AnyLine: ...indented with less than 5 spaces signifies the end of the section." 

176 assert len(warnings) == 1 

177 assert "should be 5 * 2 = 10 spaces, not 6" in warnings[0] 

178 

179 

180def test_empty_indented_lines_in_section_with_items(parse_google: ParserType) -> None: 

181 """In sections with items, don't treat lines with just indentation as items. 

182 

183 Parameters: 

184 parse_google: Fixture parser. 

185 """ 

186 docstring = "Returns:\n only_item: Description.\n \n \n\nSomething." 

187 sections, _ = parse_google(docstring) 

188 assert len(sections) == 2 

189 assert len(sections[0].value) == 1 

190 

191 

192@pytest.mark.parametrize( 

193 "section", 

194 [ 

195 "Attributes", 

196 "Other Parameters", 

197 "Parameters", 

198 "Raises", 

199 "Receives", 

200 "Returns", 

201 "Warns", 

202 "Yields", 

203 ], 

204) 

205def test_starting_item_description_on_new_line(parse_google: ParserType, section: str) -> None: 

206 """In sections with items, allow starting item descriptions on a new (indented) line. 

207 

208 Parameters: 

209 parse_google: Fixture parser. 

210 section: A parametrized section name. 

211 """ 

212 docstring = f"\n{section}:\n only_item:\n Description." 

213 sections, _ = parse_google(docstring) 

214 assert len(sections) == 1 

215 assert len(sections[0].value) == 1 

216 assert sections[0].value[0].description.strip() == "Description." 

217 

218 

219# ============================================================================================= 

220# Annotations 

221def test_parse_without_parent(parse_google: ParserType) -> None: 

222 """Parse a docstring without a parent function. 

223 

224 Parameters: 

225 parse_google: Fixture parser. 

226 """ 

227 sections, warnings = parse_google( 

228 """ 

229 Parameters: 

230 void: SEGFAULT. 

231 niet: SEGFAULT. 

232 nada: SEGFAULT. 

233 rien: SEGFAULT. 

234 

235 Keyword Args: 

236 keywd: SEGFAULT. 

237 

238 Exceptions: 

239 GlobalError: when nothing works as expected. 

240 

241 Returns: 

242 Itself. 

243 """, 

244 ) 

245 

246 assert len(sections) == 4 

247 assert len(warnings) == 6 # missing annotations for parameters and return 

248 for warning in warnings[:-1]: 

249 assert "parameter" in warning 

250 assert "return" in warnings[-1] 

251 

252 

253def test_parse_without_annotations(parse_google: ParserType) -> None: 

254 """Parse a function docstring without signature annotations. 

255 

256 Parameters: 

257 parse_google: Fixture parser. 

258 """ 

259 docstring = """ 

260 Parameters: 

261 x: X value. 

262 

263 Keyword Args: 

264 y: Y value. 

265 

266 Returns: 

267 Sum X + Y + Z. 

268 """ 

269 

270 sections, warnings = parse_google( 

271 docstring, 

272 parent=Function( 

273 "func", 

274 parameters=Parameters( 

275 Parameter("x"), 

276 Parameter("y"), 

277 ), 

278 ), 

279 ) 

280 assert len(sections) == 3 

281 assert len(warnings) == 3 

282 for warning in warnings[:-1]: 

283 assert "parameter" in warning 

284 assert "return" in warnings[-1] 

285 

286 

287def test_parse_with_annotations(parse_google: ParserType) -> None: 

288 """Parse a function docstring with signature annotations. 

289 

290 Parameters: 

291 parse_google: Fixture parser. 

292 """ 

293 docstring = """ 

294 Parameters: 

295 x: X value. 

296 

297 Keyword Parameters: 

298 y: Y value. 

299 

300 Returns: 

301 Sum X + Y. 

302 """ 

303 

304 sections, warnings = parse_google( 

305 docstring, 

306 parent=Function( 

307 "func", 

308 parameters=Parameters( 

309 Parameter("x", annotation="int"), 

310 Parameter("y", annotation="int"), 

311 ), 

312 returns="int", 

313 ), 

314 ) 

315 assert len(sections) == 3 

316 assert not warnings 

317 

318 

319# ============================================================================================= 

320# Sections 

321def test_parse_attributes_section(parse_google: ParserType) -> None: 

322 """Parse Attributes sections. 

323 

324 Parameters: 

325 parse_google: Fixture parser. 

326 """ 

327 docstring = """ 

328 Attributes: 

329 hey: Hey. 

330 ho: Ho. 

331 """ 

332 

333 sections, warnings = parse_google(docstring) 

334 assert len(sections) == 1 

335 assert not warnings 

336 

337 

338def test_parse_functions_section(parse_google: ParserType) -> None: 

339 """Parse Functions/Methods sections. 

340 

341 Parameters: 

342 parse_google: Fixture parser. 

343 """ 

344 docstring = """ 

345 Functions: 

346 f(a, b=2): Hello. 

347 g: Hi. 

348 

349 Methods: 

350 f(a, b=2): Hello. 

351 g: Hi. 

352 """ 

353 

354 sections, warnings = parse_google(docstring) 

355 assert len(sections) == 2 

356 for section in sections: 

357 assert section.kind is DocstringSectionKind.functions 

358 func_f = section.value[0] 

359 assert func_f.name == "f" 

360 assert func_f.signature == "f(a, b=2)" 

361 assert func_f.description == "Hello." 

362 func_g = section.value[1] 

363 assert func_g.name == "g" 

364 assert func_g.signature is None 

365 assert func_g.description == "Hi." 

366 assert not warnings 

367 

368 

369def test_parse_classes_section(parse_google: ParserType) -> None: 

370 """Parse Classes sections. 

371 

372 Parameters: 

373 parse_google: Fixture parser. 

374 """ 

375 docstring = """ 

376 Classes: 

377 C(a, b=2): Hello. 

378 D: Hi. 

379 """ 

380 

381 sections, warnings = parse_google(docstring) 

382 assert len(sections) == 1 

383 assert sections[0].kind is DocstringSectionKind.classes 

384 class_c = sections[0].value[0] 

385 assert class_c.name == "C" 

386 assert class_c.signature == "C(a, b=2)" 

387 assert class_c.description == "Hello." 

388 class_d = sections[0].value[1] 

389 assert class_d.name == "D" 

390 assert class_d.signature is None 

391 assert class_d.description == "Hi." 

392 assert not warnings 

393 

394 

395def test_parse_modules_section(parse_google: ParserType) -> None: 

396 """Parse Modules sections. 

397 

398 Parameters: 

399 parse_google: Fixture parser. 

400 """ 

401 docstring = """ 

402 Modules: 

403 m: Hello. 

404 n: Hi. 

405 """ 

406 

407 sections, warnings = parse_google(docstring) 

408 assert len(sections) == 1 

409 assert sections[0].kind is DocstringSectionKind.modules 

410 module_m = sections[0].value[0] 

411 assert module_m.name == "m" 

412 assert module_m.description == "Hello." 

413 module_n = sections[0].value[1] 

414 assert module_n.name == "n" 

415 assert module_n.description == "Hi." 

416 assert not warnings 

417 

418 

419def test_parse_examples_sections(parse_google: ParserType) -> None: 

420 """Parse a function docstring with examples. 

421 

422 Parameters: 

423 parse_google: Fixture parser. 

424 """ 

425 docstring = """ 

426 Examples: 

427 Some examples that will create a unified code block: 

428 

429 >>> 2 + 2 == 5 

430 False 

431 >>> print("examples") 

432 "examples" 

433 

434 This is just a random comment in the examples section. 

435 

436 These examples will generate two different code blocks. Note the blank line. 

437 

438 >>> print("I'm in the first code block!") 

439 "I'm in the first code block!" 

440 

441 >>> print("I'm in other code block!") 

442 "I'm in other code block!" 

443 

444 We also can write multiline examples: 

445 

446 >>> x = 3 + 2 # doctest: +SKIP 

447 >>> y = x + 10 

448 >>> y 

449 15 

450 

451 This is just a typical Python code block: 

452 

453 ```python 

454 print("examples") 

455 return 2 + 2 

456 ``` 

457 

458 Even if it contains doctests, the following block is still considered a normal code-block. 

459 

460 ```pycon 

461 >>> print("examples") 

462 "examples" 

463 >>> 2 + 2 

464 4 

465 ``` 

466 

467 The blank line before an example is optional. 

468 >>> x = 3 

469 >>> y = "apple" 

470 >>> z = False 

471 >>> l = [x, y, z] 

472 >>> my_print_list_function(l) 

473 3 

474 "apple" 

475 False 

476 """ 

477 

478 sections, warnings = parse_google( 

479 docstring, 

480 parent=Function( 

481 "func", 

482 parameters=Parameters( 

483 Parameter("x", annotation="int"), 

484 Parameter("y", annotation="int"), 

485 ), 

486 returns="int", 

487 ), 

488 trim_doctest_flags=False, 

489 ) 

490 assert len(sections) == 1 

491 examples = sections[0] 

492 assert len(examples.value) == 9 

493 assert examples.value[6][1].startswith(">>> x = 3 + 2 # doctest: +SKIP") 

494 assert not warnings 

495 

496 

497def test_parse_yields_section(parse_google: ParserType) -> None: 

498 """Parse Yields section. 

499 

500 Parameters: 

501 parse_google: Fixture parser. 

502 """ 

503 docstring = """ 

504 Yields: 

505 x: Floats. 

506 (int): Integers. 

507 y (int): Same. 

508 """ 

509 

510 sections, warnings = parse_google(docstring) 

511 assert len(sections) == 1 

512 annotated = sections[0].value[0] 

513 assert annotated.name == "x" 

514 assert annotated.annotation is None 

515 assert annotated.description == "Floats." 

516 annotated = sections[0].value[1] 

517 assert annotated.name == "" 

518 assert annotated.annotation == "int" 

519 assert annotated.description == "Integers." 

520 annotated = sections[0].value[2] 

521 assert annotated.name == "y" 

522 assert annotated.annotation == "int" 

523 assert annotated.description == "Same." 

524 assert len(warnings) == 1 

525 assert "'x'" in warnings[0] 

526 

527 

528def test_invalid_sections(parse_google: ParserType) -> None: 

529 """Warn on invalid sections. 

530 

531 Parameters: 

532 parse_google: Fixture parser. 

533 """ 

534 docstring = """ 

535 Parameters: 

536 Exceptions: 

537 Exceptions: 

538 

539 Returns: 

540 Note: 

541 

542 Important: 

543 """ 

544 

545 sections, warnings = parse_google(docstring) 

546 assert len(sections) == 1 

547 assert not warnings 

548 

549 

550# ============================================================================================= 

551# Parameters sections 

552def test_parse_args_and_kwargs(parse_google: ParserType) -> None: 

553 """Parse args and kwargs. 

554 

555 Parameters: 

556 parse_google: Fixture parser. 

557 """ 

558 docstring = """ 

559 Parameters: 

560 a (str): a parameter. 

561 *args (str): args parameters. 

562 **kwargs (str): kwargs parameters. 

563 """ 

564 

565 sections, warnings = parse_google(docstring) 

566 assert len(sections) == 1 

567 expected_parameters = {"a": "a parameter.", "*args": "args parameters.", "**kwargs": "kwargs parameters."} 

568 for parameter in sections[0].value: 

569 assert parameter.name in expected_parameters 

570 assert expected_parameters[parameter.name] == parameter.description 

571 assert not warnings 

572 

573 

574def test_parse_args_kwargs_keyword_only(parse_google: ParserType) -> None: 

575 """Parse args and kwargs. 

576 

577 Parameters: 

578 parse_google: Fixture parser. 

579 """ 

580 docstring = """ 

581 Parameters: 

582 a (str): a parameter. 

583 *args (str): args parameters. 

584 

585 Keyword Args: 

586 **kwargs (str): kwargs parameters. 

587 """ 

588 

589 sections, warnings = parse_google(docstring) 

590 assert len(sections) == 2 

591 expected_parameters = {"a": "a parameter.", "*args": "args parameters."} 

592 for parameter in sections[0].value: 

593 assert parameter.name in expected_parameters 

594 assert expected_parameters[parameter.name] == parameter.description 

595 

596 expected_parameters = {"**kwargs": "kwargs parameters."} 

597 for kwarg in sections[1].value: 

598 assert kwarg.name in expected_parameters 

599 assert expected_parameters[kwarg.name] == kwarg.description 

600 

601 assert not warnings 

602 

603 

604def test_parse_types_in_docstring(parse_google: ParserType) -> None: 

605 """Parse types in docstring. 

606 

607 Parameters: 

608 parse_google: Fixture parser. 

609 """ 

610 docstring = """ 

611 Parameters: 

612 x (int): X value. 

613 

614 Keyword Args: 

615 y (int): Y value. 

616 

617 Returns: 

618 s (int): Sum X + Y + Z. 

619 """ 

620 

621 sections, warnings = parse_google( 

622 docstring, 

623 parent=Function( 

624 "func", 

625 parameters=Parameters( 

626 Parameter("x"), 

627 Parameter("y"), 

628 ), 

629 ), 

630 ) 

631 assert len(sections) == 3 

632 assert not warnings 

633 

634 assert sections[0].kind is DocstringSectionKind.parameters 

635 assert sections[1].kind is DocstringSectionKind.other_parameters 

636 assert sections[2].kind is DocstringSectionKind.returns 

637 

638 (argx,) = sections[0].value 

639 (argy,) = sections[1].value 

640 (returns,) = sections[2].value 

641 

642 assert argx.name == "x" 

643 assert argx.annotation.name == "int" 

644 assert argx.annotation.canonical_path == "int" 

645 assert argx.description == "X value." 

646 assert argx.value is None 

647 

648 assert argy.name == "y" 

649 assert argy.annotation.name == "int" 

650 assert argy.annotation.canonical_path == "int" 

651 assert argy.description == "Y value." 

652 assert argy.value is None 

653 

654 assert returns.annotation.name == "int" 

655 assert returns.annotation.canonical_path == "int" 

656 assert returns.description == "Sum X + Y + Z." 

657 

658 

659def test_parse_optional_type_in_docstring(parse_google: ParserType) -> None: 

660 """Parse optional types in docstring. 

661 

662 Parameters: 

663 parse_google: Fixture parser. 

664 """ 

665 docstring = """ 

666 Parameters: 

667 x (int): X value. 

668 y (int, optional): Y value. 

669 

670 Keyword Args: 

671 z (int, optional): Z value. 

672 """ 

673 

674 sections, warnings = parse_google( 

675 docstring, 

676 parent=Function( 

677 "func", 

678 parameters=Parameters( 

679 Parameter("x", default="1"), 

680 Parameter("y", default="None"), 

681 Parameter("z", default="None"), 

682 ), 

683 ), 

684 ) 

685 assert len(sections) == 2 

686 assert not warnings 

687 

688 assert sections[0].kind is DocstringSectionKind.parameters 

689 assert sections[1].kind is DocstringSectionKind.other_parameters 

690 

691 argx, argy = sections[0].value 

692 (argz,) = sections[1].value 

693 

694 assert argx.name == "x" 

695 assert argx.annotation.name == "int" 

696 assert argx.annotation.canonical_path == "int" 

697 assert argx.description == "X value." 

698 assert argx.value == "1" 

699 

700 assert argy.name == "y" 

701 assert argy.annotation.name == "int" 

702 assert argy.annotation.canonical_path == "int" 

703 assert argy.description == "Y value." 

704 assert argy.value == "None" 

705 

706 assert argz.name == "z" 

707 assert argz.annotation.name == "int" 

708 assert argz.annotation.canonical_path == "int" 

709 assert argz.description == "Z value." 

710 assert argz.value == "None" 

711 

712 

713def test_prefer_docstring_types_over_annotations(parse_google: ParserType) -> None: 

714 """Prefer the docstring type over the annotation. 

715 

716 Parameters: 

717 parse_google: Fixture parser. 

718 """ 

719 docstring = """ 

720 Parameters: 

721 x (str): X value. 

722 

723 Keyword Args: 

724 y (str): Y value. 

725 

726 Returns: 

727 (str): Sum X + Y + Z. 

728 """ 

729 

730 sections, warnings = parse_google( 

731 docstring, 

732 parent=Function( 

733 "func", 

734 parameters=Parameters( 

735 Parameter("x", annotation="int"), 

736 Parameter("y", annotation="int"), 

737 ), 

738 returns="int", 

739 ), 

740 ) 

741 assert len(sections) == 3 

742 assert not warnings 

743 

744 assert sections[0].kind is DocstringSectionKind.parameters 

745 assert sections[1].kind is DocstringSectionKind.other_parameters 

746 assert sections[2].kind is DocstringSectionKind.returns 

747 

748 (argx,) = sections[0].value 

749 (argy,) = sections[1].value 

750 (returns,) = sections[2].value 

751 

752 assert argx.name == "x" 

753 assert argx.annotation.name == "str" 

754 assert argx.annotation.canonical_path == "str" 

755 assert argx.description == "X value." 

756 

757 assert argy.name == "y" 

758 assert argy.annotation.name == "str" 

759 assert argy.annotation.canonical_path == "str" 

760 assert argy.description == "Y value." 

761 

762 assert returns.annotation.name == "str" 

763 assert returns.annotation.canonical_path == "str" 

764 assert returns.description == "Sum X + Y + Z." 

765 

766 

767def test_parameter_line_without_colon(parse_google: ParserType) -> None: 

768 """Warn when missing colon. 

769 

770 Parameters: 

771 parse_google: Fixture parser. 

772 """ 

773 docstring = """ 

774 Parameters: 

775 x is an integer. 

776 """ 

777 

778 sections, warnings = parse_google(docstring) 

779 assert len(sections) == 0 # empty sections are discarded 

780 assert len(warnings) == 1 

781 assert "pair" in warnings[0] 

782 

783 

784def test_parameter_line_without_colon_keyword_only(parse_google: ParserType) -> None: 

785 """Warn when missing colon. 

786 

787 Parameters: 

788 parse_google: Fixture parser. 

789 """ 

790 docstring = """ 

791 Keyword Args: 

792 x is an integer. 

793 """ 

794 

795 sections, warnings = parse_google(docstring) 

796 assert len(sections) == 0 # empty sections are discarded 

797 assert len(warnings) == 1 

798 assert "pair" in warnings[0] 

799 

800 

801def test_warn_about_unknown_parameters(parse_google: ParserType) -> None: 

802 """Warn about unknown parameters in "Parameters" sections. 

803 

804 Parameters: 

805 parse_google: Fixture parser. 

806 """ 

807 docstring = """ 

808 Parameters: 

809 x (int): Integer. 

810 y (int): Integer. 

811 """ 

812 

813 _, warnings = parse_google( 

814 docstring, 

815 parent=Function( 

816 "func", 

817 parameters=Parameters( 

818 Parameter("a"), 

819 Parameter("y"), 

820 ), 

821 ), 

822 ) 

823 assert len(warnings) == 1 

824 assert "'x' does not appear in the function signature" in warnings[0] 

825 

826 

827def test_never_warn_about_unknown_other_parameters(parse_google: ParserType) -> None: 

828 """Never warn about unknown parameters in "Other parameters" sections. 

829 

830 Parameters: 

831 parse_google: Fixture parser. 

832 """ 

833 docstring = """ 

834 Other Parameters: 

835 x (int): Integer. 

836 z (int): Integer. 

837 """ 

838 

839 _, warnings = parse_google( 

840 docstring, 

841 parent=Function( 

842 "func", 

843 parameters=Parameters( 

844 Parameter("a"), 

845 Parameter("y"), 

846 ), 

847 ), 

848 ) 

849 assert not warnings 

850 

851 

852def test_unknown_params_scan_doesnt_crash_without_parameters(parse_google: ParserType) -> None: 

853 """Assert we don't crash when parsing parameters sections and parent object does not have parameters. 

854 

855 Parameters: 

856 parse_google: Fixture parser. 

857 """ 

858 docstring = """ 

859 Parameters: 

860 this (str): This. 

861 that (str): That. 

862 """ 

863 

864 _, warnings = parse_google(docstring, parent=Module("mod")) 

865 assert not warnings 

866 

867 

868def test_class_uses_init_parameters(parse_google: ParserType) -> None: 

869 """Assert we use the `__init__` parameters when parsing classes' parameters sections. 

870 

871 Parameters: 

872 parse_google: Fixture parser. 

873 """ 

874 docstring = """ 

875 Parameters: 

876 x: X value. 

877 """ 

878 parent = Class("c") 

879 parent["__init__"] = Function("__init__", parameters=Parameters(Parameter("x", annotation="int"))) 

880 sections, warnings = parse_google(docstring, parent=parent) 

881 assert not warnings 

882 argx = sections[0].value[0] 

883 assert argx.name == "x" 

884 assert argx.annotation == "int" 

885 assert argx.description == "X value." 

886 

887 

888# TODO: possible feature 

889# def test_missing_parameter(parse_google: ParserType) -> None: 

890# """Warn on missing parameter in docstring. 

891# 

892# Parameters: 

893# parse_google: Fixture parser. 

894# """ 

895# docstring = """ 

896# Parameters: 

897# x: Integer. 

898# """ 

899# assert not warnings 

900 

901 

902# ============================================================================================= 

903# Attributes sections 

904def test_retrieve_attributes_annotation_from_parent(parse_google: ParserType) -> None: 

905 """Retrieve the annotations of attributes from the parent object. 

906 

907 Parameters: 

908 parse_google: Fixture parser. 

909 """ 

910 docstring = """ 

911 Summary. 

912 

913 Attributes: 

914 a: Whatever. 

915 b: Whatever. 

916 """ 

917 parent = Class("cls") 

918 parent["a"] = Attribute("a", annotation=ExprName("int")) 

919 parent["b"] = Attribute("b", annotation=ExprName("str")) 

920 sections, _ = parse_google(docstring, parent=parent) 

921 attributes = sections[1].value 

922 assert attributes[0].name == "a" 

923 assert attributes[0].annotation.name == "int" 

924 assert attributes[1].name == "b" 

925 assert attributes[1].annotation.name == "str" 

926 

927 

928# ============================================================================================= 

929# Yields sections 

930def test_parse_yields_section_with_return_annotation(parse_google: ParserType) -> None: 

931 """Parse Yields section with a return annotation in the parent function. 

932 

933 Parameters: 

934 parse_google: Fixture parser. 

935 """ 

936 docstring = """ 

937 Yields: 

938 Integers. 

939 """ 

940 

941 function = Function("func", returns="Iterator[int]") 

942 sections, warnings = parse_google(docstring, function) 

943 assert len(sections) == 1 

944 annotated = sections[0].value[0] 

945 assert annotated.annotation == "Iterator[int]" 

946 assert annotated.description == "Integers." 

947 assert not warnings 

948 

949 

950@pytest.mark.parametrize( 

951 "return_annotation", 

952 [ 

953 "Iterator[tuple[int, float]]", 

954 "Generator[tuple[int, float], ..., ...]", 

955 ], 

956) 

957def test_parse_yields_tuple_in_iterator_or_generator(parse_google: ParserType, return_annotation: str) -> None: 

958 """Parse Yields annotations in Iterator or Generator types. 

959 

960 Parameters: 

961 parse_google: Fixture parser. 

962 return_annotation: Parametrized return annotation as a string. 

963 """ 

964 docstring = """ 

965 Summary. 

966 

967 Yields: 

968 a: Whatever. 

969 b: Whatever. 

970 """ 

971 sections, _ = parse_google( 

972 docstring, 

973 parent=Function( 

974 "func", 

975 returns=parse_docstring_annotation(return_annotation, Docstring("d", parent=Function("f"))), 

976 ), 

977 ) 

978 yields = sections[1].value 

979 assert yields[0].name == "a" 

980 assert yields[0].annotation.name == "int" 

981 assert yields[1].name == "b" 

982 assert yields[1].annotation.name == "float" 

983 

984 

985@pytest.mark.parametrize( 

986 "return_annotation", 

987 [ 

988 "Iterator[int]", 

989 "Generator[int, None, None]", 

990 ], 

991) 

992def test_extract_yielded_type_with_single_return_item(parse_google: ParserType, return_annotation: str) -> None: 

993 """Extract main type annotation from Iterator or Generator. 

994 

995 Parameters: 

996 parse_google: Fixture parser. 

997 return_annotation: Parametrized return annotation as a string. 

998 """ 

999 docstring = """ 

1000 Summary. 

1001 

1002 Yields: 

1003 A number. 

1004 """ 

1005 sections, _ = parse_google( 

1006 docstring, 

1007 parent=Function( 

1008 "func", 

1009 returns=parse_docstring_annotation(return_annotation, Docstring("d", parent=Function("f"))), 

1010 ), 

1011 ) 

1012 yields = sections[1].value 

1013 assert yields[0].annotation.name == "int" 

1014 

1015 

1016def test_yield_section_in_property(parse_google: ParserType) -> None: 

1017 """No warnings when parsing Yields section in a property. 

1018 

1019 Parameters: 

1020 parse_google: Fixture parser. 

1021 """ 

1022 docstring = """ 

1023 Summary. 

1024 

1025 Yields: 

1026 A number. 

1027 """ 

1028 sections, warnings = parse_google( 

1029 docstring, 

1030 parent=Attribute( 

1031 "prop", 

1032 annotation=parse_docstring_annotation("Iterator[int]", Docstring("d", parent=Attribute("a"))), 

1033 ), 

1034 ) 

1035 assert not warnings 

1036 yields = sections[1].value 

1037 assert yields[0].annotation.name == "int" 

1038 

1039 

1040# ============================================================================================= 

1041# Receives sections 

1042def test_parse_receives_tuple_in_generator(parse_google: ParserType) -> None: 

1043 """Parse Receives annotations in Generator type. 

1044 

1045 Parameters: 

1046 parse_google: Fixture parser. 

1047 """ 

1048 docstring = """ 

1049 Summary. 

1050 

1051 Receives: 

1052 a: Whatever. 

1053 b: Whatever. 

1054 """ 

1055 sections, _ = parse_google( 

1056 docstring, 

1057 parent=Function( 

1058 "func", 

1059 returns=parse_docstring_annotation( 

1060 "Generator[..., tuple[int, float], ...]", 

1061 Docstring("d", parent=Function("f")), 

1062 ), 

1063 ), 

1064 ) 

1065 receives = sections[1].value 

1066 assert receives[0].name == "a" 

1067 assert receives[0].annotation.name == "int" 

1068 assert receives[1].name == "b" 

1069 assert receives[1].annotation.name == "float" 

1070 

1071 

1072@pytest.mark.parametrize( 

1073 "return_annotation", 

1074 [ 

1075 "Generator[int, float, None]", 

1076 ], 

1077) 

1078def test_extract_received_type_with_single_return_item(parse_google: ParserType, return_annotation: str) -> None: 

1079 """Extract main type annotation from Iterator or Generator. 

1080 

1081 Parameters: 

1082 parse_google: Fixture parser. 

1083 return_annotation: Parametrized return annotation as a string. 

1084 """ 

1085 docstring = """ 

1086 Summary. 

1087 

1088 Receives: 

1089 A floating point number. 

1090 """ 

1091 sections, _ = parse_google( 

1092 docstring, 

1093 parent=Function( 

1094 "func", 

1095 returns=parse_docstring_annotation(return_annotation, Docstring("d", parent=Function("f"))), 

1096 ), 

1097 ) 

1098 receives = sections[1].value 

1099 assert receives[0].annotation.name == "float" 

1100 

1101 

1102# ============================================================================================= 

1103# Returns sections 

1104def test_parse_returns_tuple_in_generator(parse_google: ParserType) -> None: 

1105 """Parse Returns annotations in Generator type. 

1106 

1107 Parameters: 

1108 parse_google: Fixture parser. 

1109 """ 

1110 docstring = """ 

1111 Summary. 

1112 

1113 Returns: 

1114 a: Whatever. 

1115 b: Whatever. 

1116 """ 

1117 sections, _ = parse_google( 

1118 docstring, 

1119 parent=Function( 

1120 "func", 

1121 returns=parse_docstring_annotation( 

1122 "Generator[..., ..., tuple[int, float]]", 

1123 Docstring("d", parent=Function("f")), 

1124 ), 

1125 ), 

1126 ) 

1127 returns = sections[1].value 

1128 assert returns[0].name == "a" 

1129 assert returns[0].annotation.name == "int" 

1130 assert returns[1].name == "b" 

1131 assert returns[1].annotation.name == "float" 

1132 

1133 

1134# ============================================================================================= 

1135# Parser special features 

1136def test_parse_admonitions(parse_google: ParserType) -> None: 

1137 """Parse admonitions. 

1138 

1139 Parameters: 

1140 parse_google: Fixture parser. 

1141 """ 

1142 docstring = """ 

1143 Important note: 

1144 Hello. 

1145 

1146 Note: With title. 

1147 Hello again. 

1148 

1149 Something: 

1150 Something. 

1151 """ 

1152 

1153 sections, warnings = parse_google(docstring) 

1154 assert len(sections) == 3 

1155 assert not warnings 

1156 assert sections[0].title == "Important note" 

1157 assert sections[0].value.kind == "important-note" 

1158 assert sections[0].value.contents == "Hello." 

1159 assert sections[1].title == "With title." 

1160 assert sections[1].value.kind == "note" 

1161 assert sections[1].value.contents == "Hello again." 

1162 assert sections[2].title == "Something" 

1163 assert sections[2].value.kind == "something" 

1164 assert sections[2].value.contents == "Something." 

1165 

1166 

1167@pytest.mark.parametrize( 

1168 "docstring", 

1169 [ 

1170 """ 

1171 ****************************** 

1172 This looks like an admonition: 

1173 ****************************** 

1174 """, 

1175 """ 

1176 Warning: this line also looks 

1177 like an admonition. 

1178 """, 

1179 """ 

1180 Matching but not an admonition: 

1181 

1182 

1183 

1184 - Multiple empty lines above. 

1185 """, 

1186 """Last line:""", 

1187 ], 

1188) 

1189def test_handle_false_admonitions_correctly(parse_google: ParserType, docstring: str) -> None: 

1190 """Correctly handle lines that look like admonitions. 

1191 

1192 Parameters: 

1193 parse_google: Fixture parser. 

1194 docstring: The docstring to parse (parametrized). 

1195 """ 

1196 sections, warnings = parse_google(docstring) 

1197 assert len(sections) == 1 

1198 assert sections[0].kind is DocstringSectionKind.text 

1199 assert len(sections[0].value.splitlines()) == len(inspect.cleandoc(docstring).splitlines()) 

1200 assert not warnings 

1201 

1202 

1203def test_dont_insert_admonition_before_current_section(parse_google: ParserType) -> None: 

1204 """Check that admonitions are inserted at the right place. 

1205 

1206 Parameters: 

1207 parse_google: Fixture parser. 

1208 """ 

1209 docstring = """ 

1210 Summary. 

1211 

1212 Short description. 

1213 

1214 Info: 

1215 Something useful. 

1216 """ 

1217 sections, _ = parse_google(docstring) 

1218 assert len(sections) == 2 

1219 assert sections[0].kind is DocstringSectionKind.text 

1220 assert sections[1].kind is DocstringSectionKind.admonition 

1221 

1222 

1223@pytest.mark.parametrize( 

1224 "docstring", 

1225 [ 

1226 "", 

1227 "\n", 

1228 "\n\n", 

1229 "Summary.", 

1230 "Summary.\n\n\n", 

1231 "Summary.\n\nParagraph.", 

1232 "Summary\non two lines.", 

1233 "Summary\non two lines.\n\nParagraph.", 

1234 ], 

1235) 

1236def test_ignore_init_summary(parse_google: ParserType, docstring: str) -> None: 

1237 """Correctly ignore summary in `__init__` methods' docstrings. 

1238 

1239 Parameters: 

1240 parse_google: Fixture parser. 

1241 docstring: The docstring to parse_google (parametrized). 

1242 """ 

1243 sections, _ = parse_google(docstring, parent=Function("__init__", parent=Class("C")), ignore_init_summary=True) 

1244 for section in sections: 

1245 assert "Summary" not in section.value 

1246 

1247 if docstring.strip(): 

1248 sections, _ = parse_google(docstring, parent=Function("__init__", parent=Module("M")), ignore_init_summary=True) 

1249 assert "Summary" in sections[0].value 

1250 sections, _ = parse_google(docstring, parent=Function("f", parent=Class("C")), ignore_init_summary=True) 

1251 assert "Summary" in sections[0].value 

1252 sections, _ = parse_google(docstring, ignore_init_summary=True) 

1253 assert "Summary" in sections[0].value 

1254 

1255 

1256@pytest.mark.parametrize( 

1257 "docstring", 

1258 [ 

1259 """ 

1260 Examples: 

1261 Base case 1. We want to skip the following test. 

1262 >>> 1 + 1 == 3 # doctest: +SKIP 

1263 True 

1264 """, 

1265 r""" 

1266 Examples: 

1267 Base case 2. We have a blankline test. 

1268 >>> print("a\n\nb") 

1269 a 

1270 <BLANKLINE> 

1271 b 

1272 """, 

1273 ], 

1274) 

1275def test_trim_doctest_flags_basic_example(parse_google: ParserType, docstring: str) -> None: 

1276 """Correctly parse simple example docstrings when `trim_doctest_flags` option is turned on. 

1277 

1278 Parameters: 

1279 parse_google: Fixture parser. 

1280 docstring: The docstring to parse (parametrized). 

1281 """ 

1282 sections, warnings = parse_google(docstring, trim_doctest_flags=True) 

1283 assert len(sections) == 1 

1284 assert len(sections[0].value) == 2 

1285 assert not warnings 

1286 

1287 # verify that doctest flags have indeed been trimmed 

1288 example_str = sections[0].value[1][1] 

1289 assert "# doctest: +SKIP" not in example_str 

1290 assert "<BLANKLINE>" not in example_str 

1291 

1292 

1293def test_trim_doctest_flags_multi_example(parse_google: ParserType) -> None: 

1294 """Correctly parse multiline example docstrings when `trim_doctest_flags` option is turned on. 

1295 

1296 Parameters: 

1297 parse_google: Fixture parser. 

1298 """ 

1299 docstring = r""" 

1300 Examples: 

1301 Test multiline example blocks. 

1302 We want to skip the following test. 

1303 >>> 1 + 1 == 3 # doctest: +SKIP 

1304 True 

1305 

1306 And then a few more examples here: 

1307 >>> print("a\n\nb") 

1308 a 

1309 <BLANKLINE> 

1310 b 

1311 >>> 1 + 1 == 2 # doctest: +SKIP 

1312 >>> print(list(range(1, 100))) # doctest: +ELLIPSIS 

1313 [1, 2, ..., 98, 99] 

1314 """ 

1315 sections, warnings = parse_google(docstring, trim_doctest_flags=True) 

1316 assert len(sections) == 1 

1317 assert len(sections[0].value) == 4 

1318 assert not warnings 

1319 

1320 # verify that doctest flags have indeed been trimmed 

1321 example_str = sections[0].value[1][1] 

1322 assert "# doctest: +SKIP" not in example_str 

1323 example_str = sections[0].value[3][1] 

1324 assert "<BLANKLINE>" not in example_str 

1325 assert "\n>>> print(list(range(1, 100)))\n" in example_str 

1326 

1327 

1328def test_single_line_with_trailing_whitespace(parse_google: ParserType) -> None: 

1329 """Don't crash on single line docstrings with trailing whitespace. 

1330 

1331 Parameters: 

1332 parse_google: Fixture parser. 

1333 """ 

1334 docstring = "a: b\n " 

1335 sections, warnings = parse_google(docstring, trim_doctest_flags=True) 

1336 assert len(sections) == 1 

1337 assert sections[0].kind is DocstringSectionKind.text 

1338 assert not warnings 

1339 

1340 

1341@pytest.mark.parametrize( 

1342 ("returns_multiple_items", "return_annotation", "expected"), 

1343 [ 

1344 ( 

1345 False, 

1346 None, 

1347 [DocstringReturn("", description="XXXXXXX\n YYYYYYY\nZZZZZZZ", annotation=None)], 

1348 ), 

1349 ( 

1350 False, 

1351 "tuple[int, int]", 

1352 [DocstringReturn("", description="XXXXXXX\n YYYYYYY\nZZZZZZZ", annotation="tuple[int, int]")], 

1353 ), 

1354 ( 

1355 True, 

1356 None, 

1357 [ 

1358 DocstringReturn("", description="XXXXXXX\nYYYYYYY", annotation=None), 

1359 DocstringReturn("", description="ZZZZZZZ", annotation=None), 

1360 ], 

1361 ), 

1362 ( 

1363 True, 

1364 "tuple[int,int]", 

1365 [ 

1366 DocstringReturn("", description="XXXXXXX\nYYYYYYY", annotation="int"), 

1367 DocstringReturn("", description="ZZZZZZZ", annotation="int"), 

1368 ], 

1369 ), 

1370 ], 

1371) 

1372def test_parse_returns_multiple_items( 

1373 parse_google: ParserType, 

1374 returns_multiple_items: bool, 

1375 return_annotation: str, 

1376 expected: list[DocstringReturn], 

1377) -> None: 

1378 """Parse Returns section with and without multiple items. 

1379 

1380 Parameters: 

1381 parse_google: Fixture parser. 

1382 returns_multiple_items: Whether the `Returns` section has multiple items. 

1383 return_annotation: The return annotation of the function to parse. 

1384 expected: The expected value of the parsed Returns section. 

1385 """ 

1386 parent = ( 

1387 Function("func", returns=parse_docstring_annotation(return_annotation, Docstring("d", parent=Function("f")))) 

1388 if return_annotation is not None 

1389 else None 

1390 ) 

1391 docstring = """ 

1392 Returns: 

1393 XXXXXXX 

1394 YYYYYYY 

1395 ZZZZZZZ 

1396 """ 

1397 sections, _ = parse_google( 

1398 docstring, 

1399 returns_multiple_items=returns_multiple_items, 

1400 parent=parent, 

1401 ) 

1402 

1403 assert len(sections) == 1 

1404 assert len(sections[0].value) == len(expected) 

1405 

1406 for annotated, expected_ in zip(sections[0].value, expected): 

1407 assert annotated.name == expected_.name 

1408 assert str(annotated.annotation) == str(expected_.annotation) 

1409 assert annotated.description == expected_.description 

1410 

1411 

1412@pytest.mark.parametrize( 

1413 ("returns_multiple_items", "return_annotation", "expected"), 

1414 [ 

1415 ( 

1416 False, 

1417 None, 

1418 [DocstringYield("", description="XXXXXXX\n YYYYYYY\nZZZZZZZ", annotation=None)], 

1419 ), 

1420 ( 

1421 False, 

1422 "Iterator[tuple[int, int]]", 

1423 [DocstringYield("", description="XXXXXXX\n YYYYYYY\nZZZZZZZ", annotation="tuple[int, int]")], 

1424 ), 

1425 ( 

1426 True, 

1427 None, 

1428 [ 

1429 DocstringYield("", description="XXXXXXX\nYYYYYYY", annotation=None), 

1430 DocstringYield("", description="ZZZZZZZ", annotation=None), 

1431 ], 

1432 ), 

1433 ( 

1434 True, 

1435 "Iterator[tuple[int,int]]", 

1436 [ 

1437 DocstringYield("", description="XXXXXXX\nYYYYYYY", annotation="int"), 

1438 DocstringYield("", description="ZZZZZZZ", annotation="int"), 

1439 ], 

1440 ), 

1441 ], 

1442) 

1443def test_parse_yields_multiple_items( 

1444 parse_google: ParserType, 

1445 returns_multiple_items: bool, 

1446 return_annotation: str, 

1447 expected: list[DocstringYield], 

1448) -> None: 

1449 """Parse Returns section with and without multiple items. 

1450 

1451 Parameters: 

1452 parse_google: Fixture parser. 

1453 returns_multiple_items: Whether the `Returns` and `Yields` sections have multiple items. 

1454 return_annotation: The return annotation of the function to parse. Usually an `Iterator`. 

1455 expected: The expected value of the parsed Yields section. 

1456 """ 

1457 parent = ( 

1458 Function("func", returns=parse_docstring_annotation(return_annotation, Docstring("d", parent=Function("f")))) 

1459 if return_annotation is not None 

1460 else None 

1461 ) 

1462 docstring = """ 

1463 Yields: 

1464 XXXXXXX 

1465 YYYYYYY 

1466 ZZZZZZZ 

1467 """ 

1468 sections, _ = parse_google( 

1469 docstring, 

1470 returns_multiple_items=returns_multiple_items, 

1471 parent=parent, 

1472 ) 

1473 

1474 assert len(sections) == 1 

1475 assert len(sections[0].value) == len(expected) 

1476 

1477 for annotated, expected_ in zip(sections[0].value, expected): 

1478 assert annotated.name == expected_.name 

1479 assert str(annotated.annotation) == str(expected_.annotation) 

1480 assert annotated.description == expected_.description 

1481 

1482 

1483@pytest.mark.parametrize( 

1484 ("receives_multiple_items", "return_annotation", "expected"), 

1485 [ 

1486 ( 

1487 False, 

1488 None, 

1489 [DocstringReceive("", description="XXXXXXX\n YYYYYYY\nZZZZZZZ", annotation=None)], 

1490 ), 

1491 ( 

1492 False, 

1493 "Generator[..., tuple[int, int], ...]", 

1494 [DocstringReceive("", description="XXXXXXX\n YYYYYYY\nZZZZZZZ", annotation="tuple[int, int]")], 

1495 ), 

1496 ( 

1497 True, 

1498 None, 

1499 [ 

1500 DocstringReceive("", description="XXXXXXX\nYYYYYYY", annotation=None), 

1501 DocstringReceive("", description="ZZZZZZZ", annotation=None), 

1502 ], 

1503 ), 

1504 ( 

1505 True, 

1506 "Generator[..., tuple[int, int], ...]", 

1507 [ 

1508 DocstringReceive("", description="XXXXXXX\nYYYYYYY", annotation="int"), 

1509 DocstringReceive("", description="ZZZZZZZ", annotation="int"), 

1510 ], 

1511 ), 

1512 ], 

1513) 

1514def test_parse_receives_multiple_items( 

1515 parse_google: ParserType, 

1516 receives_multiple_items: bool, 

1517 return_annotation: str, 

1518 expected: list[DocstringReceive], 

1519) -> None: 

1520 """Parse Returns section with and without multiple items. 

1521 

1522 Parameters: 

1523 parse_google: Fixture parser. 

1524 receives_multiple_items: Whether the `Receives` section has multiple items. 

1525 return_annotation: The return annotation of the function to parse. Usually a `Generator`. 

1526 expected: The expected value of the parsed Receives section. 

1527 """ 

1528 parent = ( 

1529 Function("func", returns=parse_docstring_annotation(return_annotation, Docstring("d", parent=Function("f")))) 

1530 if return_annotation is not None 

1531 else None 

1532 ) 

1533 docstring = """ 

1534 Receives: 

1535 XXXXXXX 

1536 YYYYYYY 

1537 ZZZZZZZ 

1538 """ 

1539 sections, _ = parse_google( 

1540 docstring, 

1541 receives_multiple_items=receives_multiple_items, 

1542 parent=parent, 

1543 ) 

1544 

1545 assert len(sections) == 1 

1546 assert len(sections[0].value) == len(expected) 

1547 

1548 for annotated, expected_ in zip(sections[0].value, expected): 

1549 assert annotated.name == expected_.name 

1550 assert str(annotated.annotation) == str(expected_.annotation) 

1551 assert annotated.description == expected_.description 

1552 

1553 

1554def test_avoid_false_positive_sections(parse_google: ParserType) -> None: 

1555 """Avoid false positive when parsing sections. 

1556 

1557 Parameters: 

1558 parse_google: Fixture parser. 

1559 """ 

1560 docstring = """ 

1561 Summary. 

1562 Modules: 

1563 Not a modules section. 

1564 No blank line before title: 

1565 Not an admonition. 

1566 

1567 Blank line after title: 

1568 

1569 Not an admonition. 

1570 

1571 Modules: 

1572 

1573 Not a modules section. 

1574 Modules: 

1575 

1576 Not a modules section. 

1577 No blank line before and blank line after: 

1578 

1579 Not an admonition. 

1580 

1581 Classes: 

1582 

1583 - Text. 

1584 """ 

1585 sections, warnings = parse_google(docstring) 

1586 assert len(sections) == 1 

1587 assert "Classes" in sections[0].value 

1588 assert "Text" in sections[0].value 

1589 assert len(warnings) == 6 

1590 assert warnings == [ 

1591 "Possible section skipped, reasons: Missing blank line above section", 

1592 "Possible admonition skipped, reasons: Missing blank line above admonition", 

1593 "Possible admonition skipped, reasons: Extraneous blank line below admonition title", 

1594 "Possible section skipped, reasons: Extraneous blank line below section title", 

1595 "Possible section skipped, reasons: Missing blank line above section; Extraneous blank line below section title", 

1596 "Possible admonition skipped, reasons: Missing blank line above admonition; Extraneous blank line below admonition title", 

1597 ] 

1598 

1599 

1600def test_type_in_returns_without_parentheses(parse_google: ParserType) -> None: 

1601 """Assert we can parse the return type without parentheses. 

1602 

1603 Parameters: 

1604 parse_google: Fixture parser. 

1605 """ 

1606 docstring = """ 

1607 Summary. 

1608 

1609 Returns: 

1610 int: Description 

1611 on several lines. 

1612 """ 

1613 sections, warnings = parse_google(docstring, returns_named_value=False) 

1614 assert len(sections) == 2 

1615 assert not warnings 

1616 retval = sections[1].value[0] 

1617 assert retval.name == "" 

1618 assert retval.annotation == "int" 

1619 assert retval.description == "Description\non several lines." 

1620 

1621 docstring = """ 

1622 Summary. 

1623 

1624 Returns: 

1625 Description 

1626 on several lines. 

1627 """ 

1628 sections, warnings = parse_google(docstring, returns_named_value=False) 

1629 assert len(sections) == 2 

1630 assert len(warnings) == 1 

1631 retval = sections[1].value[0] 

1632 assert retval.name == "" 

1633 assert retval.annotation is None 

1634 assert retval.description == "Description\non several lines." 

1635 

1636 

1637def test_type_in_yields_without_parentheses(parse_google: ParserType) -> None: 

1638 """Assert we can parse the return type without parentheses. 

1639 

1640 Parameters: 

1641 parse_google: Fixture parser. 

1642 """ 

1643 docstring = """ 

1644 Summary. 

1645 

1646 Yields: 

1647 int: Description 

1648 on several lines. 

1649 """ 

1650 sections, warnings = parse_google(docstring, returns_named_value=False) 

1651 assert len(sections) == 2 

1652 assert not warnings 

1653 retval = sections[1].value[0] 

1654 assert retval.name == "" 

1655 assert retval.annotation == "int" 

1656 assert retval.description == "Description\non several lines." 

1657 

1658 docstring = """ 

1659 Summary. 

1660 

1661 Yields: 

1662 Description 

1663 on several lines. 

1664 """ 

1665 sections, warnings = parse_google(docstring, returns_named_value=False) 

1666 assert len(sections) == 2 

1667 assert len(warnings) == 1 

1668 retval = sections[1].value[0] 

1669 assert retval.name == "" 

1670 assert retval.annotation is None 

1671 assert retval.description == "Description\non several lines." 

1672 

1673 

1674def test_type_in_receives_without_parentheses(parse_google: ParserType) -> None: 

1675 """Assert we can parse the return type without parentheses. 

1676 

1677 Parameters: 

1678 parse_google: Fixture parser. 

1679 """ 

1680 docstring = """ 

1681 Summary. 

1682 

1683 Receives: 

1684 int: Description 

1685 on several lines. 

1686 """ 

1687 sections, warnings = parse_google(docstring, receives_named_value=False) 

1688 assert len(sections) == 2 

1689 assert not warnings 

1690 retval = sections[1].value[0] 

1691 assert retval.name == "" 

1692 assert retval.annotation == "int" 

1693 assert retval.description == "Description\non several lines." 

1694 

1695 docstring = """ 

1696 Summary. 

1697 

1698 Receives: 

1699 Description 

1700 on several lines. 

1701 """ 

1702 sections, warnings = parse_google(docstring, receives_named_value=False) 

1703 assert len(sections) == 2 

1704 assert len(warnings) == 1 

1705 retval = sections[1].value[0] 

1706 assert retval.name == "" 

1707 assert retval.annotation is None 

1708 assert retval.description == "Description\non several lines." 

1709 

1710 

1711def test_reading_property_type_in_summary(parse_google: ParserType) -> None: 

1712 """Assert we can parse the return type of properties in their summary. 

1713 

1714 Parameters: 

1715 parse_google: Fixture parser. 

1716 """ 

1717 docstring = "str: Description of the property." 

1718 parent = Attribute("prop") 

1719 parent.labels.add("property") 

1720 sections, warnings = parse_google(docstring, returns_type_in_property_summary=True, parent=parent) 

1721 assert len(sections) == 2 

1722 assert sections[0].kind is DocstringSectionKind.text 

1723 assert sections[1].kind is DocstringSectionKind.returns 

1724 retval = sections[1].value[0] 

1725 assert retval.name == "" 

1726 assert retval.annotation.name == "str" 

1727 assert retval.description == ""