@alloy-js/python 0.3.0-dev.0 → 0.3.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/src/builtins/python.d.ts +3 -0
  2. package/dist/src/builtins/python.d.ts.map +1 -1
  3. package/dist/src/builtins/python.js +6 -0
  4. package/dist/src/builtins/python.js.map +1 -1
  5. package/dist/src/components/ClassDeclaration.d.ts.map +1 -1
  6. package/dist/src/components/ClassDeclaration.js +9 -3
  7. package/dist/src/components/ClassDeclaration.js.map +1 -1
  8. package/dist/src/components/DataclassDeclaration.d.ts +41 -0
  9. package/dist/src/components/DataclassDeclaration.d.ts.map +1 -0
  10. package/dist/src/components/DataclassDeclaration.js +150 -0
  11. package/dist/src/components/DataclassDeclaration.js.map +1 -0
  12. package/dist/src/components/FunctionBase.d.ts.map +1 -1
  13. package/dist/src/components/FunctionBase.js +10 -3
  14. package/dist/src/components/FunctionBase.js.map +1 -1
  15. package/dist/src/components/PyDoc.d.ts +1 -1
  16. package/dist/src/components/PyDoc.d.ts.map +1 -1
  17. package/dist/src/components/PyDoc.js +59 -15
  18. package/dist/src/components/PyDoc.js.map +1 -1
  19. package/dist/src/components/UnionTypeExpression.d.ts.map +1 -1
  20. package/dist/src/components/UnionTypeExpression.js +6 -6
  21. package/dist/src/components/UnionTypeExpression.js.map +1 -1
  22. package/dist/src/components/index.d.ts +1 -0
  23. package/dist/src/components/index.d.ts.map +1 -1
  24. package/dist/src/components/index.js +1 -0
  25. package/dist/src/components/index.js.map +1 -1
  26. package/dist/test/dataclassdeclarations.test.d.ts +2 -0
  27. package/dist/test/dataclassdeclarations.test.d.ts.map +1 -0
  28. package/dist/test/dataclassdeclarations.test.js +630 -0
  29. package/dist/test/dataclassdeclarations.test.js.map +1 -0
  30. package/dist/test/pydocs.test.js +23 -34
  31. package/dist/test/pydocs.test.js.map +1 -1
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +2 -2
  34. package/src/builtins/python.ts +7 -0
  35. package/src/components/ClassDeclaration.tsx +4 -4
  36. package/src/components/DataclassDeclaration.tsx +185 -0
  37. package/src/components/FunctionBase.tsx +4 -3
  38. package/src/components/PyDoc.tsx +75 -22
  39. package/src/components/UnionTypeExpression.tsx +4 -7
  40. package/src/components/index.ts +1 -0
  41. package/temp/api.json +267 -0
  42. package/test/dataclassdeclarations.test.tsx +585 -0
  43. package/test/pydocs.test.tsx +23 -41
@@ -0,0 +1,585 @@
1
+ import { Prose, namekey } from "@alloy-js/core";
2
+ import { d } from "@alloy-js/core/testing";
3
+ import { describe, expect, it } from "vitest";
4
+ import { dataclassesModule } from "../src/builtins/python.js";
5
+ import * as py from "../src/index.js";
6
+ import { toSourceText } from "./utils.jsx";
7
+
8
+ describe("DataclassDeclaration", () => {
9
+ it("Creates a dataclass with a class doc", () => {
10
+ const doc = (
11
+ <py.ClassDoc description={[<Prose>Represents a user.</Prose>]} />
12
+ );
13
+ const res = toSourceText(
14
+ [
15
+ <py.SourceFile path="user.py">
16
+ <py.DataclassDeclaration name="User" doc={doc} />
17
+ </py.SourceFile>,
18
+ ],
19
+ { externals: [dataclassesModule] },
20
+ );
21
+
22
+ expect(res).toRenderTo(
23
+ d`
24
+ from dataclasses import dataclass
25
+
26
+ @dataclass
27
+ class User:
28
+ """
29
+ Represents a user.
30
+ """
31
+
32
+ pass
33
+
34
+
35
+ `,
36
+ );
37
+ });
38
+
39
+ it("Creates a dataclass with fields and defaults", () => {
40
+ const res = toSourceText(
41
+ [
42
+ <py.SourceFile path="user.py">
43
+ <py.DataclassDeclaration name="User">
44
+ <py.VariableDeclaration
45
+ instanceVariable
46
+ omitNone
47
+ name="id"
48
+ type="int"
49
+ />
50
+ <py.VariableDeclaration
51
+ instanceVariable
52
+ name={namekey("_", { ignoreNamePolicy: true })}
53
+ type={dataclassesModule["."].KW_ONLY}
54
+ omitNone
55
+ />
56
+ <py.VariableDeclaration
57
+ instanceVariable
58
+ name="name"
59
+ type="str"
60
+ initializer={"Anonymous"}
61
+ />
62
+ </py.DataclassDeclaration>
63
+ </py.SourceFile>,
64
+ ],
65
+ { externals: [dataclassesModule] },
66
+ );
67
+
68
+ expect(res).toRenderTo(
69
+ d`
70
+ from dataclasses import dataclass
71
+ from dataclasses import KW_ONLY
72
+
73
+ @dataclass
74
+ class User:
75
+ id: int
76
+ _: KW_ONLY
77
+ name: str = "Anonymous"
78
+
79
+
80
+ `,
81
+ );
82
+ });
83
+
84
+ it("Creates a dataclass with keyword arguments", () => {
85
+ const res = toSourceText(
86
+ [
87
+ <py.SourceFile path="user.py">
88
+ <py.DataclassDeclaration name="User" frozen slots kwOnly>
89
+ <py.VariableDeclaration
90
+ instanceVariable
91
+ omitNone
92
+ name="id"
93
+ type="int"
94
+ />
95
+ </py.DataclassDeclaration>
96
+ </py.SourceFile>,
97
+ ],
98
+ { externals: [dataclassesModule] },
99
+ );
100
+
101
+ expect(res).toRenderTo(
102
+ d`
103
+ from dataclasses import dataclass
104
+
105
+ @dataclass(frozen=True, slots=True, kw_only=True)
106
+ class User:
107
+ id: int
108
+
109
+
110
+ `,
111
+ );
112
+ });
113
+
114
+ it("Creates a dataclass with all keyword arguments", () => {
115
+ const res = toSourceText(
116
+ [
117
+ <py.SourceFile path="user.py">
118
+ <py.DataclassDeclaration
119
+ name="User"
120
+ init
121
+ repr={false}
122
+ eq
123
+ order={false}
124
+ unsafeHash
125
+ frozen
126
+ matchArgs={false}
127
+ kwOnly
128
+ slots
129
+ weakrefSlot={false}
130
+ />
131
+ </py.SourceFile>,
132
+ ],
133
+ { externals: [dataclassesModule] },
134
+ );
135
+
136
+ expect(res).toRenderTo(
137
+ d`
138
+ from dataclasses import dataclass
139
+
140
+ @dataclass(init=True, repr=False, eq=True, order=False, unsafe_hash=True, frozen=True, match_args=False, kw_only=True, slots=True, weakref_slot=False)
141
+ class User:
142
+ pass
143
+
144
+
145
+ `,
146
+ );
147
+ });
148
+
149
+ it("Throws error when weakref_slot=True without slots=True", () => {
150
+ expect(() =>
151
+ toSourceText(
152
+ [
153
+ <py.SourceFile path="user.py">
154
+ <py.DataclassDeclaration name="User" weakrefSlot />
155
+ </py.SourceFile>,
156
+ ],
157
+ { externals: [dataclassesModule] },
158
+ ),
159
+ ).toThrowError(
160
+ /weakref_slot=True requires slots=True in @dataclass decorator/,
161
+ );
162
+ });
163
+
164
+ it("Allows weakref_slot=True when slots=True", () => {
165
+ const res = toSourceText(
166
+ [
167
+ <py.SourceFile path="user.py">
168
+ <py.DataclassDeclaration name="User" slots weakrefSlot />
169
+ </py.SourceFile>,
170
+ ],
171
+ { externals: [dataclassesModule] },
172
+ );
173
+ expect(res).toRenderTo(
174
+ d`
175
+ from dataclasses import dataclass
176
+
177
+ @dataclass(slots=True, weakref_slot=True)
178
+ class User:
179
+ pass
180
+
181
+
182
+ `,
183
+ );
184
+ });
185
+
186
+ it("Throws error when order=True and eq=False", () => {
187
+ expect(() =>
188
+ toSourceText(
189
+ [
190
+ <py.SourceFile path="user.py">
191
+ <py.DataclassDeclaration name="User" order eq={false} />
192
+ </py.SourceFile>,
193
+ ],
194
+ { externals: [dataclassesModule] },
195
+ ),
196
+ ).toThrowError(/order=True requires eq=True/);
197
+ });
198
+
199
+ it("Creates a dataclass with order=True and no conflicting methods", () => {
200
+ const res = toSourceText(
201
+ [
202
+ <py.SourceFile path="user.py">
203
+ <py.DataclassDeclaration name="User" order />
204
+ </py.SourceFile>,
205
+ ],
206
+ { externals: [dataclassesModule] },
207
+ );
208
+ expect(res).toRenderTo(
209
+ d`
210
+ from dataclasses import dataclass
211
+
212
+ @dataclass(order=True)
213
+ class User:
214
+ pass
215
+
216
+
217
+ `,
218
+ );
219
+ });
220
+
221
+ it("Throws error when order=True and class defines __lt__", () => {
222
+ expect(() =>
223
+ toSourceText(
224
+ [
225
+ <py.SourceFile path="user.py">
226
+ <py.DataclassDeclaration name="User" order>
227
+ <py.DunderMethodDeclaration name="__lt__" />
228
+ </py.DataclassDeclaration>
229
+ </py.SourceFile>,
230
+ ],
231
+ { externals: [dataclassesModule] },
232
+ ),
233
+ ).toThrowError(
234
+ /Cannot specify order=True when the class already defines __lt__\(\)/,
235
+ );
236
+ });
237
+
238
+ it("Throws error when order=True and class defines __le__", () => {
239
+ expect(() =>
240
+ toSourceText(
241
+ [
242
+ <py.SourceFile path="user.py">
243
+ <py.DataclassDeclaration name="User" order>
244
+ <py.DunderMethodDeclaration name="__le__" />
245
+ </py.DataclassDeclaration>
246
+ </py.SourceFile>,
247
+ ],
248
+ { externals: [dataclassesModule] },
249
+ ),
250
+ ).toThrowError(
251
+ /Cannot specify order=True when the class already defines __le__\(\)/,
252
+ );
253
+ });
254
+
255
+ it("Throws error when order=True and class defines __gt__", () => {
256
+ expect(() =>
257
+ toSourceText(
258
+ [
259
+ <py.SourceFile path="user.py">
260
+ <py.DataclassDeclaration name="User" order>
261
+ <py.DunderMethodDeclaration name="__gt__" />
262
+ </py.DataclassDeclaration>
263
+ </py.SourceFile>,
264
+ ],
265
+ { externals: [dataclassesModule] },
266
+ ),
267
+ ).toThrowError(
268
+ /Cannot specify order=True when the class already defines __gt__\(\)/,
269
+ );
270
+ });
271
+
272
+ it("Throws error when order=True and class defines __ge__", () => {
273
+ expect(() =>
274
+ toSourceText(
275
+ [
276
+ <py.SourceFile path="user.py">
277
+ <py.DataclassDeclaration name="User" order>
278
+ <py.DunderMethodDeclaration name="__ge__" />
279
+ </py.DataclassDeclaration>
280
+ </py.SourceFile>,
281
+ ],
282
+ { externals: [dataclassesModule] },
283
+ ),
284
+ ).toThrowError(
285
+ /Cannot specify order=True when the class already defines __ge__\(\)/,
286
+ );
287
+ });
288
+
289
+ it("Throws error when order=True and a wrapper defines __lt__", () => {
290
+ function Wrapper() {
291
+ return <py.DunderMethodDeclaration name="__lt__" />;
292
+ }
293
+ expect(() =>
294
+ toSourceText(
295
+ [
296
+ <py.SourceFile path="user.py">
297
+ <py.DataclassDeclaration name="User" order>
298
+ <Wrapper />
299
+ </py.DataclassDeclaration>
300
+ </py.SourceFile>,
301
+ ],
302
+ { externals: [dataclassesModule] },
303
+ ),
304
+ ).toThrowError(
305
+ /Cannot specify order=True when the class already defines __lt__\(\)/,
306
+ );
307
+ });
308
+
309
+ it("Throws error when unsafe_hash=True and class defines __hash__", () => {
310
+ expect(() =>
311
+ toSourceText(
312
+ [
313
+ <py.SourceFile path="user.py">
314
+ <py.DataclassDeclaration name="User" unsafeHash>
315
+ <py.DunderMethodDeclaration name="__hash__" />
316
+ </py.DataclassDeclaration>
317
+ </py.SourceFile>,
318
+ ],
319
+ { externals: [dataclassesModule] },
320
+ ),
321
+ ).toThrowError(
322
+ /Cannot specify unsafe_hash=True when the class already defines __hash__\(\)/,
323
+ );
324
+ });
325
+
326
+ it("Throws error when frozen=True and class defines __setattr__", () => {
327
+ expect(() =>
328
+ toSourceText(
329
+ [
330
+ <py.SourceFile path="user.py">
331
+ <py.DataclassDeclaration name="User" frozen>
332
+ <py.DunderMethodDeclaration name="__setattr__" />
333
+ </py.DataclassDeclaration>
334
+ </py.SourceFile>,
335
+ ],
336
+ { externals: [dataclassesModule] },
337
+ ),
338
+ ).toThrowError(
339
+ /Cannot specify frozen=True when the class already defines __setattr__\(\)/,
340
+ );
341
+ });
342
+
343
+ it("Throws errorwhen frozen=True and class defines __delattr__", () => {
344
+ expect(() =>
345
+ toSourceText(
346
+ [
347
+ <py.SourceFile path="user.py">
348
+ <py.DataclassDeclaration name="User" frozen>
349
+ <py.DunderMethodDeclaration name="__delattr__" />
350
+ </py.DataclassDeclaration>
351
+ </py.SourceFile>,
352
+ ],
353
+ { externals: [dataclassesModule] },
354
+ ),
355
+ ).toThrowError(
356
+ /Cannot specify frozen=True when the class already defines __delattr__\(\)/,
357
+ );
358
+ });
359
+
360
+ it("Throws error when slots=True and class defines __slots__", () => {
361
+ expect(() =>
362
+ toSourceText(
363
+ [
364
+ <py.SourceFile path="user.py">
365
+ <py.DataclassDeclaration name="User" slots>
366
+ <py.DunderMethodDeclaration name="__slots__" />
367
+ </py.DataclassDeclaration>
368
+ </py.SourceFile>,
369
+ ],
370
+ { externals: [dataclassesModule] },
371
+ ),
372
+ ).toThrowError(
373
+ /Cannot specify slots=True when the class already defines __slots__\(\)/,
374
+ );
375
+ });
376
+
377
+ it("Creates a dataclass with kw_only=True on decorator (sentinel not used)", () => {
378
+ const res = toSourceText(
379
+ [
380
+ <py.SourceFile path="user.py">
381
+ <py.DataclassDeclaration name="User" kwOnly>
382
+ <py.VariableDeclaration
383
+ instanceVariable
384
+ omitNone
385
+ name="id"
386
+ type="int"
387
+ />
388
+ </py.DataclassDeclaration>
389
+ </py.SourceFile>,
390
+ ],
391
+ { externals: [dataclassesModule] },
392
+ );
393
+ expect(res).toRenderTo(
394
+ d`
395
+ from dataclasses import dataclass
396
+
397
+ @dataclass(kw_only=True)
398
+ class User:
399
+ id: int
400
+
401
+
402
+ `,
403
+ );
404
+ });
405
+
406
+ it("Creates a dataclass with base classes", () => {
407
+ const res = toSourceText(
408
+ [
409
+ <py.SourceFile path="user.py">
410
+ <py.DataclassDeclaration name="User" bases={["Base"]} />
411
+ </py.SourceFile>,
412
+ ],
413
+ { externals: [dataclassesModule] },
414
+ );
415
+
416
+ expect(res).toRenderTo(
417
+ d`
418
+ from dataclasses import dataclass
419
+
420
+ @dataclass
421
+ class User(Base):
422
+ pass
423
+
424
+
425
+ `,
426
+ );
427
+ });
428
+
429
+ it("Throws error when more than one KW_ONLY sentinel is present", () => {
430
+ expect(() =>
431
+ toSourceText(
432
+ [
433
+ <py.SourceFile path="user.py">
434
+ <py.DataclassDeclaration name="User">
435
+ <py.VariableDeclaration
436
+ instanceVariable
437
+ name={namekey("_", { ignoreNamePolicy: true })}
438
+ type={dataclassesModule["."].KW_ONLY}
439
+ omitNone
440
+ />
441
+ <py.VariableDeclaration
442
+ instanceVariable
443
+ name={namekey("_", { ignoreNamePolicy: true })}
444
+ type={dataclassesModule["."].KW_ONLY}
445
+ omitNone
446
+ />
447
+ </py.DataclassDeclaration>
448
+ </py.SourceFile>,
449
+ ],
450
+ { externals: [dataclassesModule] },
451
+ ),
452
+ ).toThrowError(/Only one KW_ONLY sentinel is allowed per dataclass body/);
453
+ });
454
+
455
+ it("Will raise arg validation errors first over member conflicts", () => {
456
+ expect(() =>
457
+ toSourceText(
458
+ [
459
+ <py.SourceFile path="user.py">
460
+ <py.DataclassDeclaration name="User" order eq={false}>
461
+ <py.DunderMethodDeclaration name="__lt__" />
462
+ </py.DataclassDeclaration>
463
+ </py.SourceFile>,
464
+ ],
465
+ { externals: [dataclassesModule] },
466
+ ),
467
+ ).toThrowError(/order=True requires eq=True/);
468
+ });
469
+
470
+ it("Does not raise errors for member conflict checks without the equivalent kwargs", () => {
471
+ expect(() =>
472
+ toSourceText(
473
+ [
474
+ <py.SourceFile path="user.py">
475
+ <py.DataclassDeclaration name="User">
476
+ <py.DunderMethodDeclaration name="__lt__" />
477
+ <py.DunderMethodDeclaration name="__slots__" />
478
+ <py.DunderMethodDeclaration name="__hash__" />
479
+ <py.DunderMethodDeclaration name="__setattr__" />
480
+ <py.DunderMethodDeclaration name="__delattr__" />
481
+ </py.DataclassDeclaration>
482
+ </py.SourceFile>,
483
+ ],
484
+ { externals: [dataclassesModule] },
485
+ ),
486
+ ).not.toThrow();
487
+ });
488
+
489
+ it("Allows unsafe_hash=True when no __hash__ is defined", () => {
490
+ const res = toSourceText(
491
+ [
492
+ <py.SourceFile path="user.py">
493
+ <py.DataclassDeclaration name="User" unsafeHash />
494
+ </py.SourceFile>,
495
+ ],
496
+ { externals: [dataclassesModule] },
497
+ );
498
+ expect(res).toRenderTo(
499
+ d`
500
+ from dataclasses import dataclass
501
+
502
+ @dataclass(unsafe_hash=True)
503
+ class User:
504
+ pass
505
+
506
+
507
+ `,
508
+ );
509
+ });
510
+
511
+ it("Counts KW_ONLY sentinels through wrappers (symbol-level)", () => {
512
+ function Wrapper() {
513
+ return (
514
+ <py.VariableDeclaration
515
+ instanceVariable
516
+ name={namekey("_", { ignoreNamePolicy: true })}
517
+ type={dataclassesModule["."].KW_ONLY}
518
+ omitNone
519
+ />
520
+ );
521
+ }
522
+ expect(() =>
523
+ toSourceText(
524
+ [
525
+ <py.SourceFile path="user.py">
526
+ <py.DataclassDeclaration name="User">
527
+ <py.VariableDeclaration
528
+ instanceVariable
529
+ name={namekey("_", { ignoreNamePolicy: true })}
530
+ type={dataclassesModule["."].KW_ONLY}
531
+ omitNone
532
+ />
533
+ <Wrapper />
534
+ </py.DataclassDeclaration>
535
+ </py.SourceFile>,
536
+ ],
537
+ { externals: [dataclassesModule] },
538
+ ),
539
+ ).toThrowError(/Only one KW_ONLY sentinel is allowed per dataclass body/);
540
+ });
541
+
542
+ it("Allows frozen=True when no conflicting dunders exist", () => {
543
+ const res = toSourceText(
544
+ [
545
+ <py.SourceFile path="user.py">
546
+ <py.DataclassDeclaration name="User" frozen />
547
+ </py.SourceFile>,
548
+ ],
549
+ { externals: [dataclassesModule] },
550
+ );
551
+ expect(res).toRenderTo(
552
+ d`
553
+ from dataclasses import dataclass
554
+
555
+ @dataclass(frozen=True)
556
+ class User:
557
+ pass
558
+
559
+
560
+ `,
561
+ );
562
+ });
563
+
564
+ it("Allows slots=True when no __slots__ is defined", () => {
565
+ const res = toSourceText(
566
+ [
567
+ <py.SourceFile path="user.py">
568
+ <py.DataclassDeclaration name="User" slots />
569
+ </py.SourceFile>,
570
+ ],
571
+ { externals: [dataclassesModule] },
572
+ );
573
+ expect(res).toRenderTo(
574
+ d`
575
+ from dataclasses import dataclass
576
+
577
+ @dataclass(slots=True)
578
+ class User:
579
+ pass
580
+
581
+
582
+ `,
583
+ );
584
+ });
585
+ });
@@ -104,11 +104,7 @@ describe("PyDocExample", () => {
104
104
  <py.PyDoc>
105
105
  <Prose>This is an example of a docstring with a code sample.</Prose>
106
106
  <py.PyDocExample>
107
- print("Hello world!")
108
- <br />
109
- x = "Hello"
110
- <br />
111
- print(x)
107
+ {`print("Hello world!")\nx = "Hello"\nprint(x)`}
112
108
  </py.PyDocExample>
113
109
  </py.PyDoc>,
114
110
  ],
@@ -136,12 +132,14 @@ describe("SimpleCommentBlock", () => {
136
132
  it("renders simple comment block", () => {
137
133
  const res = toSourceText([
138
134
  <py.SimpleCommentBlock>
139
- This is a simple comment block that spans multiple lines.
135
+ This is a simple comment block that spans multiple lines and should be
136
+ split automatically.
140
137
  </py.SimpleCommentBlock>,
141
138
  ]);
142
139
  expect(res).toRenderTo(
143
140
  d`
144
- # This is a simple comment block that spans multiple lines.
141
+ # This is a simple comment block that spans multiple lines and should be split
142
+ # automatically.
145
143
 
146
144
  `,
147
145
  );
@@ -150,14 +148,13 @@ describe("SimpleCommentBlock", () => {
150
148
  it("renders comment block with line breaks", () => {
151
149
  const res = toSourceText([
152
150
  <py.SimpleCommentBlock>
153
- First line of comment.
154
- <br />
155
- Second line of comment.
151
+ First line of comment.\nSecond line of comment.
156
152
  </py.SimpleCommentBlock>,
157
153
  ]);
158
154
  expect(res).toRenderTo(
159
155
  d`
160
- # First line of comment. Second line of comment.
156
+ # First line of comment.
157
+ # Second line of comment.
161
158
 
162
159
  `,
163
160
  );
@@ -877,9 +874,7 @@ describe("New Documentation Components", () => {
877
874
  Generators have a Yields section instead of a Returns section.
878
875
  </Prose>,
879
876
  <py.PyDocExample>
880
- print([i for i in example_generator(4)])
881
- <br />
882
- [0, 1, 2, 3]
877
+ {`print([i for i in example_generator(4)])\n[0, 1, 2, 3]`}
883
878
  </py.PyDocExample>,
884
879
  ]}
885
880
  parameters={[
@@ -928,11 +923,7 @@ describe("Full example", () => {
928
923
  We will also render another paragraph after this one.
929
924
  </Prose>,
930
925
  <py.PyDocExample>
931
- print("Hello world!")
932
- <br />
933
- x = "Hello"
934
- <br />
935
- print(x)
926
+ {`print("Hello world!")\nx = "Hello"\nprint(x)`}
936
927
  </py.PyDocExample>,
937
928
  ]}
938
929
  attributes={[
@@ -1050,11 +1041,7 @@ describe("Full example", () => {
1050
1041
  We will also render another paragraph after this one.
1051
1042
  </Prose>,
1052
1043
  <py.PyDocExample>
1053
- print("Hello world!")
1054
- <br />
1055
- x = "Hello"
1056
- <br />
1057
- print(x)
1044
+ {`print("Hello world!")\nx = "Hello"\nprint(x)`}
1058
1045
  </py.PyDocExample>,
1059
1046
  ]}
1060
1047
  parameters={[
@@ -1397,23 +1384,18 @@ describe("Full example", () => {
1397
1384
  </py.ClassDeclaration>,
1398
1385
  ]);
1399
1386
 
1400
- expect(result).toRenderTo(
1401
- d`
1402
- class Person:
1403
- @property
1404
- def full_name(self) -> str:
1405
- """
1406
- The full name of the person, combining first and last name. This
1407
- property automatically formats the name with proper capitalization.
1408
- """
1409
- return "John Doe"
1410
-
1411
-
1412
-
1413
-
1414
-
1415
- `,
1416
- );
1387
+ expect(result).toRenderTo(`
1388
+ class Person:
1389
+ @property
1390
+ def full_name(self) -> str:
1391
+ """
1392
+ The full name of the person, combining first and last name. This
1393
+ property automatically formats the name with proper capitalization.
1394
+ """
1395
+ return "John Doe"
1396
+
1397
+
1398
+ `);
1417
1399
  });
1418
1400
 
1419
1401
  it("MethodDoc with FunctionDeclaration (inside class) integration", () => {