Coverage for tests/test_parsers/test_docstrings/test_restructured_text.py: 97.17%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Tests for [the `parsers.docstrings.google` module][pytkdocs.parsers.docstrings.google]."""
3import inspect
4from textwrap import dedent
6import pytest
8from pytkdocs.loader import Loader
9from pytkdocs.objects import Object
10from pytkdocs.parsers.docstrings.base import AnnotatedObject, Attribute, Parameter, Section, empty
11from pytkdocs.parsers.docstrings.restructured_text import RestructuredText
12from pytkdocs.serializer import serialize_attribute
15class DummyObject:
16 def __init__(self, signature, return_type):
17 self.path = "o"
18 self.signature = signature
19 self.type = return_type
22SOME_NAME = "foo"
23SOME_TEXT = "descriptive test text"
24SOME_EXTRA_TEXT = "more test text"
25SOME_EXCEPTION_NAME = "SomeException"
26SOME_OTHER_EXCEPTION_NAME = "SomeOtherException"
29def dedent_strip(text: str) -> str:
30 return dedent(text).strip()
33def parse(obj, strip_docstring=True):
34 """Helper to parse a docstring."""
35 return parse_detailed(inspect.getdoc(obj), inspect.signature(obj), strip_docstring=strip_docstring)
38def parse_detailed(docstring, signature=None, return_type=inspect.Signature.empty, strip_docstring=True):
39 """Helper to parse a docstring."""
40 docstring = dedent_strip(docstring) if strip_docstring else dedent(docstring)
42 return RestructuredText().parse(docstring, {"obj": DummyObject(signature, return_type)})
45def assert_parameter_equal(actual: Parameter, expected: Parameter) -> None:
46 assert actual.name == expected.name
47 assert_annotated_obj_equal(actual, expected)
48 assert actual.kind == expected.kind
49 assert actual.default == expected.default
52def assert_attribute_equal(actual: Attribute, expected: Attribute) -> None:
53 assert actual.name == expected.name
54 assert_annotated_obj_equal(actual, expected)
57def assert_annotated_obj_equal(actual: AnnotatedObject, expected: AnnotatedObject) -> None:
58 assert actual.annotation == expected.annotation
59 assert actual.description == expected.description
62def get_rst_object_documentation(dotted_fixture_subpath) -> Object:
63 return Loader(docstring_style="restructured-text").get_object_documentation(
64 f"tests.fixtures.parsing.restructured_text.{dotted_fixture_subpath}"
65 )
68@pytest.mark.parametrize(
69 "docstring",
70 [
71 "One line docstring description",
72 """
73 Multiple line docstring description.
75 With more text.
76 """,
77 ],
78)
79def test_parse__description_only_docstring__single_markdown_section(docstring):
80 sections, errors = parse_detailed(docstring)
82 assert len(sections) == 1
83 assert sections[0].type == Section.Type.MARKDOWN
84 assert sections[0].value == dedent_strip(docstring)
85 assert not errors
88def test_parse__no_description__single_markdown_section():
89 sections, errors = parse_detailed("")
91 assert len(sections) == 1
92 assert sections[0].type == Section.Type.MARKDOWN
93 assert sections[0].value == ""
94 assert not errors
97def test_parse__multiple_blank_lines_before_description__single_markdown_section():
98 sections, errors = parse_detailed(
99 """
102 Now text""",
103 strip_docstring=False,
104 )
106 assert len(sections) == 1
107 assert sections[0].type == Section.Type.MARKDOWN
108 assert sections[0].value == "Now text"
109 assert not errors
112def test_parse__description_with_initial_newline__single_markdown_section():
113 docstring = """
114 With initial newline
115 """
116 sections, errors = parse_detailed(docstring, strip_docstring=False)
118 assert len(sections) == 1
119 assert sections[0].type == Section.Type.MARKDOWN
120 assert sections[0].value == dedent_strip(docstring)
121 assert not errors
124def test_parse__param_field__param_section():
125 """Parse a simple docstring."""
126 sections, errors = parse_detailed(
127 f"""
128 Docstring with one line param.
130 :param {SOME_NAME}: {SOME_TEXT}
131 """
132 )
133 assert len(sections) == 2
134 assert sections[1].type == Section.Type.PARAMETERS
135 assert_parameter_equal(
136 sections[1].value[0], Parameter(SOME_NAME, annotation=empty, description=SOME_TEXT, kind=empty)
137 )
140def test_parse__only_param_field__empty_markdown():
141 sections, errors = parse_detailed(":param foo: text")
142 assert len(sections) == 2
143 assert sections[0].type == Section.Type.MARKDOWN
144 assert sections[0].value == ""
147@pytest.mark.parametrize(
148 "param_directive_name",
149 [
150 "param",
151 "parameter",
152 "arg",
153 "argument",
154 "key",
155 "keyword",
156 ],
157)
158def test_parse__all_param_names__param_section(param_directive_name):
159 sections, errors = parse_detailed(
160 f"""
161 Docstring with one line param.
163 :{param_directive_name} {SOME_NAME}: {SOME_TEXT}
164 """
165 )
166 assert len(sections) == 2
167 assert sections[1].type == Section.Type.PARAMETERS
168 assert_parameter_equal(
169 sections[1].value[0], Parameter(SOME_NAME, annotation=empty, description=SOME_TEXT, kind=empty)
170 )
173@pytest.mark.parametrize(
174 "docstring",
175 [
176 f"""
177 Docstring with param with continuation, no indent.
179 :param {SOME_NAME}: {SOME_TEXT}
180 {SOME_EXTRA_TEXT}
181 """,
182 f"""
183 Docstring with param with continuation, with indent.
185 :param {SOME_NAME}: {SOME_TEXT}
186 {SOME_EXTRA_TEXT}
187 """,
188 ],
189)
190def test_parse__param_field_multi_line__param_section(docstring):
191 """Parse a simple docstring."""
192 sections, errors = parse_detailed(docstring)
193 assert len(sections) == 2
194 assert sections[1].type == Section.Type.PARAMETERS
195 assert_parameter_equal(
196 sections[1].value[0],
197 Parameter(SOME_NAME, annotation=empty, description=f"{SOME_TEXT} {SOME_EXTRA_TEXT}", kind=empty),
198 )
201def test_parse__param_field_for_function__param_section_with_kind():
202 """Parse a simple docstring."""
204 def f(foo):
205 """
206 Docstring with line continuation.
208 :param foo: descriptive test text
209 """
211 sections, errors = parse(f)
212 assert len(sections) == 2
213 assert sections[1].type == Section.Type.PARAMETERS
214 assert_parameter_equal(
215 sections[1].value[0],
216 Parameter(SOME_NAME, annotation=empty, description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD),
217 )
220def test_parse__param_field_docs_type__param_section_with_type():
221 """Parse a simple docstring."""
223 def f(foo):
224 """
225 Docstring with line continuation.
227 :param str foo: descriptive test text
228 """
230 sections, errors = parse(f)
231 assert len(sections) == 2
232 assert sections[1].type == Section.Type.PARAMETERS
233 assert_parameter_equal(
234 sections[1].value[0],
235 Parameter(SOME_NAME, annotation="str", description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD),
236 )
239def test_parse__param_field_type_field__param_section_with_type():
240 """Parse a simple docstring."""
242 def f(foo):
243 """
244 Docstring with line continuation.
246 :param foo: descriptive test text
247 :type foo: str
248 """
250 sections, errors = parse(f)
251 assert len(sections) == 2
252 assert sections[1].type == Section.Type.PARAMETERS
253 assert_parameter_equal(
254 sections[1].value[0],
255 Parameter(SOME_NAME, annotation="str", description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD),
256 )
259def test_parse__param_field_type_field_first__param_section_with_type():
260 """Parse a simple docstring."""
262 def f(foo):
263 """
264 Docstring with line continuation.
266 :type foo: str
267 :param foo: descriptive test text
268 """
270 sections, errors = parse(f)
271 assert len(sections) == 2
272 assert sections[1].type == Section.Type.PARAMETERS
273 assert_parameter_equal(
274 sections[1].value[0],
275 Parameter(SOME_NAME, annotation="str", description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD),
276 )
279def test_parse__param_field_type_field_or_none__param_section_with_optional():
280 """Parse a simple docstring."""
282 def f(foo):
283 """
284 Docstring with line continuation.
286 :param foo: descriptive test text
287 :type foo: str or None
288 """
290 sections, errors = parse(f)
291 assert len(sections) == 2
292 assert sections[1].type == Section.Type.PARAMETERS
293 assert_parameter_equal(
294 sections[1].value[0],
295 Parameter(
296 SOME_NAME, annotation="Optional[str]", description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD
297 ),
298 )
301def test_parse__param_field_type_none_or_field__param_section_with_optional():
302 """Parse a simple docstring."""
304 def f(foo):
305 """
306 Docstring with line continuation.
308 :param foo: descriptive test text
309 :type foo: None or str
310 """
312 sections, errors = parse(f)
313 assert len(sections) == 2
314 assert sections[1].type == Section.Type.PARAMETERS
315 assert_parameter_equal(
316 sections[1].value[0],
317 Parameter(
318 SOME_NAME, annotation="Optional[str]", description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD
319 ),
320 )
323def test_parse__param_field_type_field_or_int__param_section_with_union():
324 """Parse a simple docstring."""
326 def f(foo):
327 """
328 Docstring with line continuation.
330 :param foo: descriptive test text
331 :type foo: str or int
332 """
334 sections, errors = parse(f)
335 assert len(sections) == 2
336 assert sections[1].type == Section.Type.PARAMETERS
337 assert_parameter_equal(
338 sections[1].value[0],
339 Parameter(
340 SOME_NAME, annotation="Union[str,int]", description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD
341 ),
342 )
345def test_parse__param_field_type_multiple__param_section_with_union():
346 """Parse a simple docstring."""
348 def f(foo):
349 """
350 Docstring with line continuation.
352 :param foo: descriptive test text
353 :type foo: str or int or float
354 """
356 sections, errors = parse(f)
357 assert len(sections) == 2
358 assert sections[1].type == Section.Type.PARAMETERS
359 assert_parameter_equal(
360 sections[1].value[0],
361 Parameter(
362 SOME_NAME,
363 annotation="Union[str,int,float]",
364 description=SOME_TEXT,
365 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
366 ),
367 )
370def test_parse__param_field_annotate_type__param_section_with_type():
371 """Parse a simple docstring."""
373 def f(foo: str):
374 """
375 Docstring with line continuation.
377 :param foo: descriptive test text
378 """
380 sections, errors = parse(f)
381 assert len(sections) == 2
382 assert sections[1].type == Section.Type.PARAMETERS
383 assert_parameter_equal(
384 sections[1].value[0],
385 Parameter(SOME_NAME, annotation=str, description=SOME_TEXT, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD),
386 )
389def test_parse__param_field_no_matching_param__result_from_docstring():
390 """Parse a simple docstring."""
392 def f(foo: str):
393 """
394 Docstring with line continuation.
396 :param other: descriptive test text
397 """
399 sections, errors = parse(f)
400 assert len(sections) == 2
401 assert sections[1].type == Section.Type.PARAMETERS
402 assert_parameter_equal(
403 sections[1].value[0],
404 Parameter("other", annotation=empty, description=SOME_TEXT, kind=empty),
405 )
408def test_parse__param_field_with_default__result_from_docstring():
409 """Parse a simple docstring."""
411 def f(foo=""):
412 """
413 Docstring with line continuation.
415 :param foo: descriptive test text
416 """
418 sections, errors = parse(f)
419 assert len(sections) == 2
420 assert sections[1].type == Section.Type.PARAMETERS
421 assert_parameter_equal(
422 sections[1].value[0],
423 Parameter(
424 "foo", annotation=empty, description=SOME_TEXT, default="", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD
425 ),
426 )
429def test_parse__param_field_no_matching_param__error_message():
430 """Parse a simple docstring."""
432 def f(foo: str):
433 """
434 Docstring with line continuation.
436 :param other: descriptive test text
437 """
439 sections, errors = parse(f)
440 assert "No matching parameter for 'other'" in errors[0]
443def test_parse__invalid_param_field_only_initial_marker__error_message():
444 """Parse a simple docstring."""
446 def f(foo: str):
447 """
448 Docstring with line continuation.
450 :param foo descriptive test text
451 """
453 sections, errors = parse(f)
454 assert "Failed to get ':directive: value' pair" in errors[0]
457def test_parse__invalid_param_field_wrong_part_count__error_message():
458 """Parse a simple docstring."""
460 def f(foo: str):
461 """
462 Docstring with line continuation.
464 :param: descriptive test text
465 """
467 sections, errors = parse(f)
468 assert "Failed to parse field directive" in errors[0]
471def test_parse__param_twice__error_message():
472 """Parse a simple docstring."""
474 def f(foo: str):
475 """
476 Docstring with line continuation.
478 :param foo: descriptive test text
479 :param foo: descriptive test text again
480 """
482 sections, errors = parse(f)
483 assert "Duplicate parameter entry for 'foo'" in errors[0]
486def test_parse__param_type_twice_doc__error_message():
487 """Parse a simple docstring."""
489 def f(foo):
490 """
491 Docstring with line continuation.
493 :param str foo: descriptive test text
494 :type foo: str
495 """
497 sections, errors = parse(f)
498 assert "Duplicate parameter information for 'foo'" in errors[0]
501def test_parse__param_type_twice_type_directive_first__error_message():
502 """Parse a simple docstring."""
504 def f(foo):
505 """
506 Docstring with line continuation.
508 :type foo: str
509 :param str foo: descriptive test text
510 """
512 sections, errors = parse(f)
513 assert "Duplicate parameter information for 'foo'" in errors[0]
516def test_parse__param_type_twice_annotated__error_message():
517 """Parse a simple docstring."""
519 def f(foo: str):
520 """
521 Docstring with line continuation.
523 :param str foo: descriptive test text
524 :type foo: str
525 """
527 sections, errors = parse(f)
528 assert "Duplicate parameter information for 'foo'" in errors[0]
531def test_parse__param_type_no_type__error_message():
532 """Parse a simple docstring."""
534 def f(foo: str):
535 """
536 Docstring with line continuation.
538 :param str foo: descriptive test text
539 :type str
540 """
542 sections, errors = parse(f)
543 assert "Failed to get ':directive: value' pair from" in errors[0]
546def test_parse__param_type_no_name__error_message():
547 """Parse a simple docstring."""
549 def f(foo: str):
550 """
551 Docstring with line continuation.
553 :param str foo: descriptive test text
554 :type: str
555 """
557 sections, errors = parse(f)
558 assert "Failed to get parameter name from" in errors[0]
561@pytest.mark.parametrize(
562 "docstring",
563 [
564 f"""
565 Docstring with param with continuation, no indent.
567 :var {SOME_NAME}: {SOME_TEXT}
568 {SOME_EXTRA_TEXT}
569 """,
570 f"""
571 Docstring with param with continuation, with indent.
573 :var {SOME_NAME}: {SOME_TEXT}
574 {SOME_EXTRA_TEXT}
575 """,
576 ],
577)
578def test_parse__attribute_field_multi_line__param_section(docstring):
579 """Parse a simple docstring."""
580 sections, errors = parse_detailed(docstring)
581 assert len(sections) == 2
582 assert sections[1].type == Section.Type.ATTRIBUTES
583 assert_attribute_equal(
584 sections[1].value[0],
585 Attribute(SOME_NAME, annotation=empty, description=f"{SOME_TEXT} {SOME_EXTRA_TEXT}"),
586 )
589@pytest.mark.parametrize(
590 "attribute_directive_name",
591 [
592 "var",
593 "ivar",
594 "cvar",
595 ],
596)
597def test_parse__all_attribute_names__param_section(attribute_directive_name):
598 sections, errors = parse_detailed(
599 f"""
600 Docstring with one line attribute.
602 :{attribute_directive_name} {SOME_NAME}: {SOME_TEXT}
603 """
604 )
605 assert len(sections) == 2
606 assert sections[1].type == Section.Type.ATTRIBUTES
607 assert_attribute_equal(
608 sections[1].value[0],
609 Attribute(SOME_NAME, annotation=empty, description=SOME_TEXT),
610 )
613def test_parse__class_attributes__attributes_section():
614 class Foo:
615 """
616 Class docstring with attributes
618 :var foo: descriptive test text
619 """
621 sections, errors = parse(Foo)
622 assert len(sections) == 2
623 assert sections[1].type == Section.Type.ATTRIBUTES
624 assert_attribute_equal(
625 sections[1].value[0],
626 Attribute(SOME_NAME, annotation=empty, description=SOME_TEXT),
627 )
630def test_parse__class_attributes_with_type__annotation_in_attributes_section():
631 class Foo:
632 """
633 Class docstring with attributes
635 :vartype foo: str
636 :var foo: descriptive test text
637 """
639 sections, errors = parse(Foo)
640 assert len(sections) == 2
641 assert sections[1].type == Section.Type.ATTRIBUTES
642 assert_attribute_equal(
643 sections[1].value[0],
644 Attribute(SOME_NAME, annotation="str", description=SOME_TEXT),
645 )
648def test_parse__attribute_invalid_directive___error():
649 class Foo:
650 """
651 Class docstring with attributes
653 :var descriptive test text
654 """
656 sections, errors = parse(Foo)
657 assert "Failed to get ':directive: value' pair from" in errors[0]
660def test_parse__attribute_no_name__error():
661 class Foo:
662 """
663 Class docstring with attributes
665 :var: descriptive test text
666 """
668 sections, errors = parse(Foo)
669 assert "Failed to parse field directive from" in errors[0]
672def test_parse__attribute_duplicate__error():
673 class Foo:
674 """
675 Class docstring with attributes
677 :var foo: descriptive test text
678 :var foo: descriptive test text
679 """
681 sections, errors = parse(Foo)
682 assert "Duplicate attribute entry for 'foo'" in errors[0]
685def test_parse__class_attributes_type_invalid__error():
686 class Foo:
687 """
688 Class docstring with attributes
690 :vartype str
691 :var foo: descriptive test text
692 """
694 sections, errors = parse(Foo)
695 assert "Failed to get ':directive: value' pair from " in errors[0]
698def test_parse__class_attributes_type_no_name__error():
699 class Foo:
700 """
701 Class docstring with attributes
703 :vartype: str
704 :var foo: descriptive test text
705 """
707 sections, errors = parse(Foo)
708 assert "Failed to get attribute name from" in errors[0]
711def test_parse__return_directive__return_section_no_type():
712 def f(foo: str):
713 """
714 Function with only return directive
716 :return: descriptive test text
717 """
718 return foo
720 sections, errors = parse(f)
721 assert len(sections) == 2
722 assert sections[1].type == Section.Type.RETURN
723 assert_annotated_obj_equal(
724 sections[1].value,
725 AnnotatedObject(annotation=empty, description=SOME_TEXT),
726 )
729def test_parse__return_directive_rtype__return_section_with_type():
730 def f(foo: str):
731 """
732 Function with only return & rtype directive
734 :return: descriptive test text
735 :rtype: str
736 """
737 return foo
739 sections, errors = parse(f)
740 assert len(sections) == 2
741 assert sections[1].type == Section.Type.RETURN
742 assert_annotated_obj_equal(
743 sections[1].value,
744 AnnotatedObject(annotation="str", description=SOME_TEXT),
745 )
748def test_parse__return_directive_rtype_first__return_section_with_type():
749 def f(foo: str):
750 """
751 Function with only return & rtype directive
753 :rtype: str
754 :return: descriptive test text
755 """
756 return foo
758 sections, errors = parse(f)
759 assert len(sections) == 2
760 assert sections[1].type == Section.Type.RETURN
761 assert_annotated_obj_equal(
762 sections[1].value,
763 AnnotatedObject(annotation="str", description=SOME_TEXT),
764 )
767def test_parse__return_directive_annotation__return_section_with_type():
768 def f(foo: str) -> str:
769 """
770 Function with return directive, rtype directive, & annotation
772 :return: descriptive test text
773 """
774 return foo
776 sections, errors = parse(f)
777 assert len(sections) == 2
778 assert sections[1].type == Section.Type.RETURN
779 assert_annotated_obj_equal(
780 sections[1].value,
781 AnnotatedObject(annotation=str, description=SOME_TEXT),
782 )
785def test_parse__return_directive_annotation__return_section_with_type_error():
786 def f(foo: str) -> str:
787 """
788 Function with return directive, rtype directive, & annotation
790 :return: descriptive test text
791 :rtype: str
792 """
793 return foo
795 sections, errors = parse(f)
796 assert len(sections) == 2
797 assert sections[1].type == Section.Type.RETURN
798 assert_annotated_obj_equal(
799 sections[1].value,
800 AnnotatedObject(annotation=str, description=SOME_TEXT),
801 )
802 assert "Duplicate type information for return" in errors[0]
805def test_parse__return_invalid__error():
806 def f(foo: str):
807 """
808 Function with only return directive
810 :return descriptive test text
811 """
812 return foo
814 sections, errors = parse(f)
815 assert "Failed to get ':directive: value' pair from " in errors[0]
818def test_parse__rtype_invalid__error():
819 def f(foo: str):
820 """
821 Function with only return directive
823 :rtype str
824 """
825 return foo
827 sections, errors = parse(f)
828 assert "Failed to get ':directive: value' pair from " in errors[0]
831def test_parse__raises_directive__exception_section():
832 def f(foo: str):
833 """
834 Function with only return directive
836 :raise SomeException: descriptive test text
837 """
838 return foo
840 sections, errors = parse(f)
841 assert len(sections) == 2
842 assert sections[1].type == Section.Type.EXCEPTIONS
843 assert_annotated_obj_equal(
844 sections[1].value[0],
845 AnnotatedObject(annotation=SOME_EXCEPTION_NAME, description=SOME_TEXT),
846 )
849def test_parse__multiple_raises_directive__exception_section_with_two():
850 def f(foo: str):
851 """
852 Function with only return directive
854 :raise SomeException: descriptive test text
855 :raise SomeOtherException: descriptive test text
856 """
857 return foo
859 sections, errors = parse(f)
860 assert len(sections) == 2
861 assert sections[1].type == Section.Type.EXCEPTIONS
862 assert_annotated_obj_equal(
863 sections[1].value[0],
864 AnnotatedObject(annotation=SOME_EXCEPTION_NAME, description=SOME_TEXT),
865 )
866 assert_annotated_obj_equal(
867 sections[1].value[1],
868 AnnotatedObject(annotation=SOME_OTHER_EXCEPTION_NAME, description=SOME_TEXT),
869 )
872@pytest.mark.parametrize(
873 "attribute_directive_name",
874 [
875 "raises",
876 "raise",
877 "except",
878 "exception",
879 ],
880)
881def test_parse__all_exception_names__param_section(attribute_directive_name):
882 sections, errors = parse_detailed(
883 f"""
884 Docstring with one line attribute.
886 :{attribute_directive_name} {SOME_EXCEPTION_NAME}: {SOME_TEXT}
887 """
888 )
889 assert len(sections) == 2
890 assert sections[1].type == Section.Type.EXCEPTIONS
891 assert_annotated_obj_equal(
892 sections[1].value[0],
893 AnnotatedObject(annotation=SOME_EXCEPTION_NAME, description=SOME_TEXT),
894 )
897def test_parse__raise_invalid__error():
898 def f(foo: str):
899 """
900 Function with only return directive
902 :raise descriptive test text
903 """
904 return foo
906 sections, errors = parse(f)
907 assert "Failed to get ':directive: value' pair from " in errors[0]
910def test_parse__raise_no_name__error():
911 def f(foo: str):
912 """
913 Function with only return directive
915 :raise: descriptive test text
916 """
917 return foo
919 sections, errors = parse(f)
920 assert "Failed to parse exception directive from" in errors[0]
923# -------------------------------
924# Fixture tests
925# -------------------------------
928def test_parse_module_attributes_section__expected_attributes_section():
929 """Parse attributes section in modules."""
930 obj = get_rst_object_documentation("docstring_attributes_section")
931 assert len(obj.docstring_sections) == 2
932 attr_section = obj.docstring_sections[1]
933 assert attr_section.type == Section.Type.ATTRIBUTES
934 assert len(attr_section.value) == 5
935 expected = [
936 {"name": "A", "annotation": "int", "description": "Alpha."},
937 # type annotation takes preference over docstring
938 {"name": "B", "annotation": "str", "description": "Beta."},
939 {"name": "C", "annotation": "bool", "description": "Gamma."},
940 {"name": "D", "annotation": "", "description": "Delta."},
941 {"name": "E", "annotation": "float", "description": "Epsilon."},
942 ]
943 assert [serialize_attribute(attr) for attr in attr_section.value] == expected
946def test_parse_module_attributes_section__expected_docstring_errors():
947 """Parse attributes section in modules."""
948 obj = get_rst_object_documentation("docstring_attributes_section")
949 assert len(obj.docstring_errors) == 1
950 assert "Duplicate attribute information for 'B'" in obj.docstring_errors[0]
953def test_property_docstring__expected_description():
954 """Parse a property docstring."""
955 class_ = get_rst_object_documentation("class_docstrings:NotDefinedYet")
956 prop = class_.attributes[0]
957 sections = prop.docstring_sections
958 assert len(sections) == 2
959 assert sections[0].type == Section.Type.MARKDOWN
960 assert (
961 sections[0].value
962 == "This property returns `self`.\n\nIt's fun because you can call it like `obj.ha.ha.ha.ha.ha.ha...`."
963 )
966def test_property_docstring__expected_return():
967 """Parse a property docstring."""
968 class_ = get_rst_object_documentation("class_docstrings:NotDefinedYet")
969 prop = class_.attributes[0]
970 sections = prop.docstring_sections
971 assert len(sections) == 2
972 assert sections[1].type == Section.Type.RETURN
973 assert_annotated_obj_equal(sections[1].value, AnnotatedObject("NotDefinedYet", "self!"))
976def test_property_class_init__expected_description():
977 class_ = get_rst_object_documentation("class_docstrings:ClassInitFunction")
978 init = class_.methods[0]
979 sections = init.docstring_sections
980 assert len(sections) == 2
981 assert sections[0].type == Section.Type.MARKDOWN
982 assert sections[0].value == "Initialize instance."
985def test_class_init__expected_param():
986 class_ = get_rst_object_documentation("class_docstrings:ClassInitFunction")
987 init = class_.methods[0]
988 sections = init.docstring_sections
989 assert len(sections) == 2
990 assert sections[1].type == Section.Type.PARAMETERS
991 param_section = sections[1]
992 assert_parameter_equal(
993 param_section.value[0], Parameter("value", str, "Value to store", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
994 )
995 assert_parameter_equal(
996 param_section.value[1],
997 Parameter("other", "int", "Other value with default", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, default=1),
998 )
1001def test_member_function___expected_param():
1002 class_ = get_rst_object_documentation("class_docstrings:ClassWithFunction")
1003 init = class_.methods[0]
1004 sections = init.docstring_sections
1005 assert len(sections) == 3
1006 param_section = sections[1]
1007 assert param_section.type == Section.Type.PARAMETERS
1008 assert_parameter_equal(
1009 param_section.value[0], Parameter("value", str, "Value to store", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
1010 )
1011 assert_parameter_equal(
1012 param_section.value[1],
1013 Parameter("other", "int", "Other value with default", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, default=1),
1014 )
1017def test_member_function___expected_return():
1018 class_ = get_rst_object_documentation("class_docstrings:ClassWithFunction")
1019 init = class_.methods[0]
1020 sections = init.docstring_sections
1021 assert len(sections) == 3
1022 assert sections[2].type == Section.Type.RETURN
1023 assert_annotated_obj_equal(sections[2].value, AnnotatedObject(str, "Concatenated result"))
1026def test_property_docstring__no_errors():
1027 """Parse a property docstring."""
1028 class_ = get_rst_object_documentation("class_docstrings:NotDefinedYet")
1029 prop = class_.attributes[0]
1030 assert not prop.docstring_errors