Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
singlestore-labs
GitHub Repository: singlestore-labs/singlestoredb-python
Path: blob/main/singlestoredb/docstring/tests/test_google.py
469 views
1
"""Tests for Google-style docstring routines."""
2
import typing as T
3
4
import pytest
5
6
import singlestoredb.docstring.google as google
7
from singlestoredb.docstring.common import ParseError
8
from singlestoredb.docstring.common import RenderingStyle
9
from singlestoredb.docstring.google import compose
10
from singlestoredb.docstring.google import GoogleParser
11
from singlestoredb.docstring.google import parse
12
from singlestoredb.docstring.google import Section
13
from singlestoredb.docstring.google import SectionType
14
15
16
def test_google_parser_unknown_section() -> None:
17
"""Test parsing an unknown section with default GoogleParser
18
configuration.
19
"""
20
parser = GoogleParser()
21
docstring = parser.parse(
22
"""
23
Unknown:
24
spam: a
25
""",
26
)
27
assert docstring.short_description == 'Unknown:'
28
assert docstring.long_description == 'spam: a'
29
assert len(docstring.meta) == 0
30
31
32
def test_google_parser_multi_line_parameter_type() -> None:
33
"""Test parsing a multi-line parameter type with default GoogleParser"""
34
parser = GoogleParser()
35
docstring = parser.parse(
36
"""Description of the function.
37
38
Args:
39
output_type (Literal["searchResults", "sourcedAnswer",
40
"structured"]): The type of output.
41
This can be one of the following:
42
- "searchResults": Represents the search results.
43
- "sourcedAnswer": Represents a sourced answer.
44
- "structured": Represents a structured output format.
45
46
Returns:
47
bool: Indicates success or failure.
48
49
""",
50
)
51
assert docstring.params[0].arg_name == 'output_type'
52
53
54
def test_google_parser_custom_sections() -> None:
55
"""Test parsing an unknown section with custom GoogleParser
56
configuration.
57
"""
58
parser = GoogleParser(
59
[
60
Section('DESCRIPTION', 'desc', SectionType.SINGULAR),
61
Section('ARGUMENTS', 'param', SectionType.MULTIPLE),
62
Section('ATTRIBUTES', 'attribute', SectionType.MULTIPLE),
63
Section('EXAMPLES', 'examples', SectionType.SINGULAR),
64
],
65
title_colon=False,
66
)
67
docstring = parser.parse(
68
"""
69
DESCRIPTION
70
This is the description.
71
72
ARGUMENTS
73
arg1: first arg
74
arg2: second arg
75
76
ATTRIBUTES
77
attr1: first attribute
78
attr2: second attribute
79
80
EXAMPLES
81
Many examples
82
More examples
83
""",
84
)
85
86
assert docstring.short_description is None
87
assert docstring.long_description is None
88
assert len(docstring.meta) == 6
89
assert docstring.meta[0].args == ['desc']
90
assert docstring.meta[0].description == 'This is the description.'
91
assert docstring.meta[1].args == ['param', 'arg1']
92
assert docstring.meta[1].description == 'first arg'
93
assert docstring.meta[2].args == ['param', 'arg2']
94
assert docstring.meta[2].description == 'second arg'
95
assert docstring.meta[3].args == ['attribute', 'attr1']
96
assert docstring.meta[3].description == 'first attribute'
97
assert docstring.meta[4].args == ['attribute', 'attr2']
98
assert docstring.meta[4].description == 'second attribute'
99
assert docstring.meta[5].args == ['examples']
100
assert docstring.meta[5].description == 'Many examples\nMore examples'
101
102
103
def test_google_parser_custom_sections_after() -> None:
104
"""Test parsing an unknown section with custom GoogleParser configuration
105
that was set at a runtime.
106
"""
107
parser = GoogleParser(title_colon=False)
108
parser.add_section(Section('Note', 'note', SectionType.SINGULAR))
109
docstring = parser.parse(
110
"""
111
short description
112
113
Note:
114
a note
115
""",
116
)
117
assert docstring.short_description == 'short description'
118
assert docstring.long_description == 'Note:\n a note'
119
120
docstring = parser.parse(
121
"""
122
short description
123
124
Note a note
125
""",
126
)
127
assert docstring.short_description == 'short description'
128
assert docstring.long_description == 'Note a note'
129
130
docstring = parser.parse(
131
"""
132
short description
133
134
Note
135
a note
136
""",
137
)
138
assert len(docstring.meta) == 1
139
assert docstring.meta[0].args == ['note']
140
assert docstring.meta[0].description == 'a note'
141
142
143
@pytest.mark.parametrize(
144
'source, expected',
145
[
146
pytest.param(None, None, id='No __doc__'),
147
('', None),
148
('\n', None),
149
('Short description', 'Short description'),
150
('\nShort description\n', 'Short description'),
151
('\n Short description\n', 'Short description'),
152
],
153
)
154
def test_short_description(
155
source: T.Optional[str], expected: T.Optional[str],
156
) -> None:
157
"""Test parsing short description."""
158
docstring = parse(source)
159
assert docstring.short_description == expected
160
assert docstring.long_description is None
161
assert not docstring.meta
162
163
164
@pytest.mark.parametrize(
165
'source, expected_short_desc, expected_long_desc, expected_blank',
166
[
167
(
168
'Short description\n\nLong description',
169
'Short description',
170
'Long description',
171
True,
172
),
173
(
174
"""
175
Short description
176
177
Long description
178
""",
179
'Short description',
180
'Long description',
181
True,
182
),
183
(
184
"""
185
Short description
186
187
Long description
188
Second line
189
""",
190
'Short description',
191
'Long description\nSecond line',
192
True,
193
),
194
(
195
'Short description\nLong description',
196
'Short description',
197
'Long description',
198
False,
199
),
200
(
201
"""
202
Short description
203
Long description
204
""",
205
'Short description',
206
'Long description',
207
False,
208
),
209
(
210
'\nShort description\nLong description\n',
211
'Short description',
212
'Long description',
213
False,
214
),
215
(
216
"""
217
Short description
218
Long description
219
Second line
220
""",
221
'Short description',
222
'Long description\nSecond line',
223
False,
224
),
225
],
226
)
227
def test_long_description(
228
source: str,
229
expected_short_desc: str,
230
expected_long_desc: str,
231
expected_blank: bool,
232
) -> None:
233
"""Test parsing long description."""
234
docstring = parse(source)
235
assert docstring.short_description == expected_short_desc
236
assert docstring.long_description == expected_long_desc
237
assert docstring.blank_after_short_description == expected_blank
238
assert not docstring.meta
239
240
241
@pytest.mark.parametrize(
242
'source, expected_short_desc, expected_long_desc, '
243
'expected_blank_short_desc, expected_blank_long_desc',
244
[
245
(
246
"""
247
Short description
248
Args:
249
asd:
250
""",
251
'Short description',
252
None,
253
False,
254
False,
255
),
256
(
257
"""
258
Short description
259
Long description
260
Args:
261
asd:
262
""",
263
'Short description',
264
'Long description',
265
False,
266
False,
267
),
268
(
269
"""
270
Short description
271
First line
272
Second line
273
Args:
274
asd:
275
""",
276
'Short description',
277
'First line\n Second line',
278
False,
279
False,
280
),
281
(
282
"""
283
Short description
284
285
First line
286
Second line
287
Args:
288
asd:
289
""",
290
'Short description',
291
'First line\n Second line',
292
True,
293
False,
294
),
295
(
296
"""
297
Short description
298
299
First line
300
Second line
301
302
Args:
303
asd:
304
""",
305
'Short description',
306
'First line\n Second line',
307
True,
308
True,
309
),
310
(
311
"""
312
Args:
313
asd:
314
""",
315
None,
316
None,
317
False,
318
False,
319
),
320
],
321
)
322
def test_meta_newlines(
323
source: str,
324
expected_short_desc: T.Optional[str],
325
expected_long_desc: T.Optional[str],
326
expected_blank_short_desc: bool,
327
expected_blank_long_desc: bool,
328
) -> None:
329
"""Test parsing newlines around description sections."""
330
docstring = parse(source)
331
assert docstring.short_description == expected_short_desc
332
assert docstring.long_description == expected_long_desc
333
assert docstring.blank_after_short_description == expected_blank_short_desc
334
assert docstring.blank_after_long_description == expected_blank_long_desc
335
assert len(docstring.meta) == 1
336
337
338
def test_meta_with_multiline_description() -> None:
339
"""Test parsing multiline meta documentation."""
340
docstring = parse(
341
"""
342
Short description
343
344
Args:
345
spam: asd
346
1
347
2
348
3
349
""",
350
)
351
assert docstring.short_description == 'Short description'
352
assert len(docstring.meta) == 1
353
assert docstring.meta[0].args == ['param', 'spam']
354
assert isinstance(docstring.meta[0], google.DocstringParam)
355
assert docstring.meta[0].arg_name == 'spam'
356
assert docstring.meta[0].description == 'asd\n1\n 2\n3'
357
358
359
def test_default_args() -> None:
360
"""Test parsing default arguments."""
361
docstring = parse(
362
"""A sample function
363
364
A function the demonstrates docstrings
365
366
Args:
367
arg1 (int): The firsty arg
368
arg2 (str): The second arg
369
arg3 (float, optional): The third arg. Defaults to 1.0.
370
arg4 (Optional[Dict[str, Any]], optional): The last arg. Defaults to None.
371
arg5 (str, optional): The fifth arg. Defaults to DEFAULT_ARG5.
372
373
Returns:
374
Mapping[str, Any]: The args packed in a mapping
375
""",
376
)
377
assert docstring is not None
378
assert len(docstring.params) == 5
379
380
arg4 = docstring.params[3]
381
assert arg4.arg_name == 'arg4'
382
assert arg4.is_optional
383
assert arg4.type_name == 'Optional[Dict[str, Any]]'
384
assert arg4.default == 'None'
385
assert arg4.description == 'The last arg. Defaults to None.'
386
387
388
def test_multiple_meta() -> None:
389
"""Test parsing multiple meta."""
390
docstring = parse(
391
"""
392
Short description
393
394
Args:
395
spam: asd
396
1
397
2
398
3
399
400
Raises:
401
bla: herp
402
yay: derp
403
""",
404
)
405
assert docstring.short_description == 'Short description'
406
assert len(docstring.meta) == 3
407
assert docstring.meta[0].args == ['param', 'spam']
408
assert isinstance(docstring.meta[0], google.DocstringParam)
409
assert docstring.meta[0].arg_name == 'spam'
410
assert docstring.meta[0].description == 'asd\n1\n 2\n3'
411
assert docstring.meta[1].args == ['raises', 'bla']
412
assert isinstance(docstring.meta[1], google.DocstringRaises)
413
assert docstring.meta[1].type_name == 'bla'
414
assert docstring.meta[1].description == 'herp'
415
assert isinstance(docstring.meta[2], google.DocstringRaises)
416
assert docstring.meta[2].args == ['raises', 'yay']
417
assert docstring.meta[2].type_name == 'yay'
418
assert docstring.meta[2].description == 'derp'
419
420
421
def test_params() -> None:
422
"""Test parsing params."""
423
docstring = parse('Short description')
424
assert len(docstring.params) == 0
425
426
docstring = parse(
427
"""
428
Short description
429
430
Args:
431
name: description 1
432
priority (int): description 2
433
sender (str?): description 3
434
ratio (Optional[float], optional): description 4
435
""",
436
)
437
assert len(docstring.params) == 4
438
assert docstring.params[0].arg_name == 'name'
439
assert docstring.params[0].type_name is None
440
assert docstring.params[0].description == 'description 1'
441
assert not docstring.params[0].is_optional
442
assert docstring.params[1].arg_name == 'priority'
443
assert docstring.params[1].type_name == 'int'
444
assert docstring.params[1].description == 'description 2'
445
assert not docstring.params[1].is_optional
446
assert docstring.params[2].arg_name == 'sender'
447
assert docstring.params[2].type_name == 'str'
448
assert docstring.params[2].description == 'description 3'
449
assert docstring.params[2].is_optional
450
assert docstring.params[3].arg_name == 'ratio'
451
assert docstring.params[3].type_name == 'Optional[float]'
452
assert docstring.params[3].description == 'description 4'
453
assert docstring.params[3].is_optional
454
455
docstring = parse(
456
"""
457
Short description
458
459
Args:
460
name: description 1
461
with multi-line text
462
priority (int): description 2
463
""",
464
)
465
assert len(docstring.params) == 2
466
assert docstring.params[0].arg_name == 'name'
467
assert docstring.params[0].type_name is None
468
assert docstring.params[0].description == (
469
'description 1\nwith multi-line text'
470
)
471
assert docstring.params[1].arg_name == 'priority'
472
assert docstring.params[1].type_name == 'int'
473
assert docstring.params[1].description == 'description 2'
474
475
476
def test_attributes() -> None:
477
"""Test parsing attributes."""
478
docstring = parse('Short description')
479
assert len(docstring.params) == 0
480
481
docstring = parse(
482
"""
483
Short description
484
485
Attributes:
486
name: description 1
487
priority (int): description 2
488
sender (str?): description 3
489
ratio (Optional[float], optional): description 4
490
""",
491
)
492
assert len(docstring.params) == 4
493
assert docstring.params[0].arg_name == 'name'
494
assert docstring.params[0].type_name is None
495
assert docstring.params[0].description == 'description 1'
496
assert not docstring.params[0].is_optional
497
assert docstring.params[1].arg_name == 'priority'
498
assert docstring.params[1].type_name == 'int'
499
assert docstring.params[1].description == 'description 2'
500
assert not docstring.params[1].is_optional
501
assert docstring.params[2].arg_name == 'sender'
502
assert docstring.params[2].type_name == 'str'
503
assert docstring.params[2].description == 'description 3'
504
assert docstring.params[2].is_optional
505
assert docstring.params[3].arg_name == 'ratio'
506
assert docstring.params[3].type_name == 'Optional[float]'
507
assert docstring.params[3].description == 'description 4'
508
assert docstring.params[3].is_optional
509
510
docstring = parse(
511
"""
512
Short description
513
514
Attributes:
515
name: description 1
516
with multi-line text
517
priority (int): description 2
518
""",
519
)
520
assert len(docstring.params) == 2
521
assert docstring.params[0].arg_name == 'name'
522
assert docstring.params[0].type_name is None
523
assert docstring.params[0].description == (
524
'description 1\nwith multi-line text'
525
)
526
assert docstring.params[1].arg_name == 'priority'
527
assert docstring.params[1].type_name == 'int'
528
assert docstring.params[1].description == 'description 2'
529
530
531
def test_returns() -> None:
532
"""Test parsing returns."""
533
docstring = parse(
534
"""
535
Short description
536
""",
537
)
538
assert docstring.returns is None
539
assert docstring.many_returns is not None
540
assert len(docstring.many_returns) == 0
541
542
docstring = parse(
543
"""
544
Short description
545
Returns:
546
description
547
""",
548
)
549
assert docstring.returns is not None
550
assert docstring.returns.type_name is None
551
assert docstring.returns.description == 'description'
552
assert docstring.many_returns is not None
553
assert len(docstring.many_returns) == 1
554
assert docstring.many_returns[0] == docstring.returns
555
556
docstring = parse(
557
"""
558
Short description
559
Returns:
560
description with: a colon!
561
""",
562
)
563
assert docstring.returns is not None
564
assert docstring.returns.type_name is None
565
assert docstring.returns.description == 'description with: a colon!'
566
assert docstring.many_returns is not None
567
assert len(docstring.many_returns) == 1
568
assert docstring.many_returns[0] == docstring.returns
569
570
docstring = parse(
571
"""
572
Short description
573
Returns:
574
int: description
575
""",
576
)
577
assert docstring.returns is not None
578
assert docstring.returns.type_name == 'int'
579
assert docstring.returns.description == 'description'
580
assert docstring.many_returns is not None
581
assert len(docstring.many_returns) == 1
582
assert docstring.many_returns[0] == docstring.returns
583
584
docstring = parse(
585
"""
586
Returns:
587
Optional[Mapping[str, List[int]]]: A description: with a colon
588
""",
589
)
590
assert docstring.returns is not None
591
assert docstring.returns.type_name == 'Optional[Mapping[str, List[int]]]'
592
assert docstring.returns.description == 'A description: with a colon'
593
assert docstring.many_returns is not None
594
assert len(docstring.many_returns) == 1
595
assert docstring.many_returns[0] == docstring.returns
596
597
docstring = parse(
598
"""
599
Short description
600
Yields:
601
int: description
602
""",
603
)
604
assert docstring.returns is not None
605
assert docstring.returns.type_name == 'int'
606
assert docstring.returns.description == 'description'
607
assert docstring.many_returns is not None
608
assert len(docstring.many_returns) == 1
609
assert docstring.many_returns[0] == docstring.returns
610
611
docstring = parse(
612
"""
613
Short description
614
Returns:
615
int: description
616
with much text
617
618
even some spacing
619
""",
620
)
621
assert docstring.returns is not None
622
assert docstring.returns.type_name == 'int'
623
assert docstring.returns.description == (
624
'description\nwith much text\n\neven some spacing'
625
)
626
assert docstring.many_returns is not None
627
assert len(docstring.many_returns) == 1
628
assert docstring.many_returns[0] == docstring.returns
629
630
631
def test_raises() -> None:
632
"""Test parsing raises."""
633
docstring = parse(
634
"""
635
Short description
636
""",
637
)
638
assert len(docstring.raises) == 0
639
640
docstring = parse(
641
"""
642
Short description
643
Raises:
644
ValueError: description
645
""",
646
)
647
assert len(docstring.raises) == 1
648
assert docstring.raises[0].type_name == 'ValueError'
649
assert docstring.raises[0].description == 'description'
650
651
652
def test_examples() -> None:
653
"""Test parsing examples."""
654
docstring = parse(
655
"""
656
Short description
657
Example:
658
example: 1
659
Examples:
660
long example
661
662
more here
663
""",
664
)
665
assert len(docstring.examples) == 2
666
assert docstring.examples[0].description == 'example: 1'
667
assert docstring.examples[1].description == 'long example\n\nmore here'
668
669
670
def test_broken_meta() -> None:
671
"""Test parsing broken meta."""
672
with pytest.raises(ParseError):
673
parse('Args:')
674
675
with pytest.raises(ParseError):
676
parse('Args:\n herp derp')
677
678
679
def test_unknown_meta() -> None:
680
"""Test parsing unknown meta."""
681
docstring = parse(
682
"""Short desc
683
684
Unknown 0:
685
title0: content0
686
687
Args:
688
arg0: desc0
689
arg1: desc1
690
691
Unknown1:
692
title1: content1
693
694
Unknown2:
695
title2: content2
696
""",
697
)
698
699
assert docstring.params[0].arg_name == 'arg0'
700
assert docstring.params[0].description == 'desc0'
701
assert docstring.params[1].arg_name == 'arg1'
702
assert docstring.params[1].description == 'desc1'
703
704
705
def test_broken_arguments() -> None:
706
"""Test parsing broken arguments."""
707
with pytest.raises(ParseError):
708
parse(
709
"""This is a test
710
711
Args:
712
param - poorly formatted
713
""",
714
)
715
716
717
def test_empty_example() -> None:
718
"""Test parsing empty examples section."""
719
docstring = parse(
720
"""Short description
721
722
Example:
723
724
Raises:
725
IOError: some error
726
""",
727
)
728
729
assert len(docstring.examples) == 1
730
assert docstring.examples[0].args == ['examples']
731
assert docstring.examples[0].description == ''
732
733
734
@pytest.mark.parametrize(
735
'source, expected',
736
[
737
('', ''),
738
('\n', ''),
739
('Short description', 'Short description'),
740
('\nShort description\n', 'Short description'),
741
('\n Short description\n', 'Short description'),
742
(
743
'Short description\n\nLong description',
744
'Short description\n\nLong description',
745
),
746
(
747
"""
748
Short description
749
750
Long description
751
""",
752
'Short description\n\nLong description',
753
),
754
(
755
"""
756
Short description
757
758
Long description
759
Second line
760
""",
761
'Short description\n\nLong description\nSecond line',
762
),
763
(
764
'Short description\nLong description',
765
'Short description\nLong description',
766
),
767
(
768
"""
769
Short description
770
Long description
771
""",
772
'Short description\nLong description',
773
),
774
(
775
'\nShort description\nLong description\n',
776
'Short description\nLong description',
777
),
778
(
779
"""
780
Short description
781
Long description
782
Second line
783
""",
784
'Short description\nLong description\nSecond line',
785
),
786
(
787
"""
788
Short description
789
Meta:
790
asd
791
""",
792
'Short description\nMeta:\n asd',
793
),
794
(
795
"""
796
Short description
797
Long description
798
Meta:
799
asd
800
""",
801
'Short description\nLong description\nMeta:\n asd',
802
),
803
(
804
"""
805
Short description
806
First line
807
Second line
808
Meta:
809
asd
810
""",
811
'Short description\n'
812
'First line\n'
813
' Second line\n'
814
'Meta:\n'
815
' asd',
816
),
817
(
818
"""
819
Short description
820
821
First line
822
Second line
823
Meta:
824
asd
825
""",
826
'Short description\n'
827
'\n'
828
'First line\n'
829
' Second line\n'
830
'Meta:\n'
831
' asd',
832
),
833
(
834
"""
835
Short description
836
837
First line
838
Second line
839
840
Meta:
841
asd
842
""",
843
'Short description\n'
844
'\n'
845
'First line\n'
846
' Second line\n'
847
'\n'
848
'Meta:\n'
849
' asd',
850
),
851
(
852
"""
853
Short description
854
855
Meta:
856
asd
857
1
858
2
859
3
860
""",
861
'Short description\n'
862
'\n'
863
'Meta:\n'
864
' asd\n'
865
' 1\n'
866
' 2\n'
867
' 3',
868
),
869
(
870
"""
871
Short description
872
873
Meta1:
874
asd
875
1
876
2
877
3
878
Meta2:
879
herp
880
Meta3:
881
derp
882
""",
883
'Short description\n'
884
'\n'
885
'Meta1:\n'
886
' asd\n'
887
' 1\n'
888
' 2\n'
889
' 3\n'
890
'Meta2:\n'
891
' herp\n'
892
'Meta3:\n'
893
' derp',
894
),
895
(
896
"""
897
Short description
898
899
Args:
900
name: description 1
901
priority (int): description 2
902
sender (str, optional): description 3
903
message (str, optional): description 4, defaults to 'hello'
904
multiline (str?):
905
long description 5,
906
defaults to 'bye'
907
""",
908
'Short description\n'
909
'\n'
910
'Args:\n'
911
' name: description 1\n'
912
' priority (int): description 2\n'
913
' sender (str?): description 3\n'
914
" message (str?): description 4, defaults to 'hello'\n"
915
' multiline (str?): long description 5,\n'
916
" defaults to 'bye'",
917
),
918
(
919
"""
920
Short description
921
Raises:
922
ValueError: description
923
""",
924
'Short description\nRaises:\n ValueError: description',
925
),
926
],
927
)
928
def test_compose(source: str, expected: str) -> None:
929
"""Test compose in default mode."""
930
assert compose(parse(source)) == expected
931
932
933
@pytest.mark.parametrize(
934
'source, expected',
935
[
936
(
937
"""
938
Short description
939
940
Args:
941
name: description 1
942
priority (int): description 2
943
sender (str, optional): description 3
944
message (str, optional): description 4, defaults to 'hello'
945
multiline (str?):
946
long description 5,
947
defaults to 'bye'
948
""",
949
'Short description\n'
950
'\n'
951
'Args:\n'
952
' name: description 1\n'
953
' priority (int): description 2\n'
954
' sender (str, optional): description 3\n'
955
" message (str, optional): description 4, defaults to 'hello'\n"
956
' multiline (str, optional): long description 5,\n'
957
" defaults to 'bye'",
958
),
959
],
960
)
961
def test_compose_clean(source: str, expected: str) -> None:
962
"""Test compose in clean mode."""
963
assert (
964
compose(parse(source), rendering_style=RenderingStyle.CLEAN)
965
== expected
966
)
967
968
969
@pytest.mark.parametrize(
970
'source, expected',
971
[
972
(
973
"""
974
Short description
975
976
Args:
977
name: description 1
978
priority (int): description 2
979
sender (str, optional): description 3
980
message (str, optional): description 4, defaults to 'hello'
981
multiline (str?):
982
long description 5,
983
defaults to 'bye'
984
""",
985
'Short description\n'
986
'\n'
987
'Args:\n'
988
' name:\n'
989
' description 1\n'
990
' priority (int):\n'
991
' description 2\n'
992
' sender (str, optional):\n'
993
' description 3\n'
994
' message (str, optional):\n'
995
" description 4, defaults to 'hello'\n"
996
' multiline (str, optional):\n'
997
' long description 5,\n'
998
" defaults to 'bye'",
999
),
1000
],
1001
)
1002
def test_compose_expanded(source: str, expected: str) -> None:
1003
"""Test compose in expanded mode."""
1004
assert (
1005
compose(parse(source), rendering_style=RenderingStyle.EXPANDED)
1006
== expected
1007
)
1008
1009