@alloy-js/python 0.3.0-dev.4 → 0.3.0-dev.6

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 (61) hide show
  1. package/dist/src/components/CallSignature.d.ts +6 -4
  2. package/dist/src/components/CallSignature.d.ts.map +1 -1
  3. package/dist/src/components/CallSignature.js +23 -26
  4. package/dist/src/components/CallSignature.js.map +1 -1
  5. package/dist/src/components/FutureStatement.d.ts +35 -0
  6. package/dist/src/components/FutureStatement.d.ts.map +1 -0
  7. package/dist/src/components/FutureStatement.js +31 -0
  8. package/dist/src/components/FutureStatement.js.map +1 -0
  9. package/dist/src/components/SourceFile.d.ts +8 -2
  10. package/dist/src/components/SourceFile.d.ts.map +1 -1
  11. package/dist/src/components/SourceFile.js +124 -8
  12. package/dist/src/components/SourceFile.js.map +1 -1
  13. package/dist/src/components/index.d.ts +1 -0
  14. package/dist/src/components/index.d.ts.map +1 -1
  15. package/dist/src/components/index.js +1 -0
  16. package/dist/src/components/index.js.map +1 -1
  17. package/dist/test/callsignatures.test.js +127 -0
  18. package/dist/test/callsignatures.test.js.map +1 -1
  19. package/dist/test/classdeclarations.test.js +2 -0
  20. package/dist/test/classdeclarations.test.js.map +1 -1
  21. package/dist/test/dataclassdeclarations.test.js +13 -0
  22. package/dist/test/dataclassdeclarations.test.js.map +1 -1
  23. package/dist/test/enums.test.js +7 -0
  24. package/dist/test/enums.test.js.map +1 -1
  25. package/dist/test/externals.test.js +2 -0
  26. package/dist/test/externals.test.js.map +1 -1
  27. package/dist/test/functiondeclaration.test.js +2 -0
  28. package/dist/test/functiondeclaration.test.js.map +1 -1
  29. package/dist/test/methoddeclaration.test.js +1 -0
  30. package/dist/test/methoddeclaration.test.js.map +1 -1
  31. package/dist/test/namepolicies.test.js +1 -0
  32. package/dist/test/namepolicies.test.js.map +1 -1
  33. package/dist/test/propertydeclaration.test.js +1 -0
  34. package/dist/test/propertydeclaration.test.js.map +1 -1
  35. package/dist/test/pydocs.test.js +1 -1
  36. package/dist/test/pydocs.test.js.map +1 -1
  37. package/dist/test/sourcefiles.test.js +921 -39
  38. package/dist/test/sourcefiles.test.js.map +1 -1
  39. package/dist/test/utils.d.ts +2 -2
  40. package/dist/test/utils.d.ts.map +1 -1
  41. package/dist/test/utils.js +9 -9
  42. package/dist/test/utils.js.map +1 -1
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +2 -2
  45. package/src/components/CallSignature.tsx +41 -36
  46. package/src/components/FutureStatement.tsx +38 -0
  47. package/src/components/SourceFile.tsx +128 -8
  48. package/src/components/index.ts +1 -0
  49. package/temp/api.json +169 -5
  50. package/test/callsignatures.test.tsx +110 -0
  51. package/test/classdeclarations.test.tsx +2 -0
  52. package/test/dataclassdeclarations.test.tsx +13 -0
  53. package/test/enums.test.tsx +7 -0
  54. package/test/externals.test.tsx +2 -0
  55. package/test/functiondeclaration.test.tsx +2 -0
  56. package/test/methoddeclaration.test.tsx +1 -0
  57. package/test/namepolicies.test.tsx +1 -0
  58. package/test/propertydeclaration.test.tsx +1 -0
  59. package/test/pydocs.test.tsx +1 -1
  60. package/test/sourcefiles.test.tsx +754 -48
  61. package/test/utils.tsx +10 -5
@@ -3,7 +3,8 @@ import { Prose } from "@alloy-js/core";
3
3
  import { d } from "@alloy-js/core/testing";
4
4
  import { expect, it } from "vitest";
5
5
  import * as py from "../src/index.js";
6
- import { assertFileContents, toSourceText, toSourceTextMultiple } from "./utils.js";
6
+ import { dataclassesModule } from "../src/index.js";
7
+ import { toSourceText } from "./utils.js";
7
8
 
8
9
  /**
9
10
  * toSourceText wraps the children in a SourceFile component
@@ -11,11 +12,10 @@ import { assertFileContents, toSourceText, toSourceTextMultiple } from "./utils.
11
12
  */
12
13
  it("renders an empty source file", () => {
13
14
  const result = toSourceText([]);
14
- const expected = d`
15
+ expect(result).toRenderTo(d`
15
16
 
16
17
 
17
- `;
18
- expect(result).toRenderTo(expected);
18
+ `);
19
19
  });
20
20
  it("correct formatting of source file", () => {
21
21
  const result = toSourceText([_$createComponent(py.ClassDeclaration, {
@@ -162,7 +162,7 @@ it("correct formatting of source file", () => {
162
162
  })];
163
163
  }
164
164
  })]);
165
- const expected = d`
165
+ expect(result).toRenderTo(d`
166
166
  class SomeClass:
167
167
  def some_method() -> str:
168
168
  x: int = 42
@@ -194,8 +194,7 @@ it("correct formatting of source file", () => {
194
194
 
195
195
  a.b["special-prop"]
196
196
 
197
- `;
198
- expect(result).toRenderTo(expected);
197
+ `);
199
198
  });
200
199
  it("renders module documentation correctly", () => {
201
200
  const moduleDoc = _$createComponent(py.ModuleDoc, {
@@ -217,7 +216,7 @@ it("renders module documentation correctly", () => {
217
216
  style: "google"
218
217
  });
219
218
  const content = _$createComponent(py.SourceFile, {
220
- path: "utils.py",
219
+ path: "test.py",
221
220
  doc: moduleDoc,
222
221
  get children() {
223
222
  return [_$createComponent(py.VariableDeclaration, {
@@ -232,40 +231,34 @@ it("renders module documentation correctly", () => {
232
231
  })];
233
232
  }
234
233
  });
235
- const res = toSourceTextMultiple([content]);
236
- const file = res.contents.find(f => f.kind === "file" && f.path === "utils.py");
237
- expect(file).toBeDefined();
238
- assertFileContents(res, {
239
- "utils.py": d`
240
- """
241
- This module provides utility functions for data processing. It includes
242
- functions for validation, transformation, and analysis.
234
+ expect(toSourceText(content)).toRenderTo(d`
235
+ """
236
+ This module provides utility functions for data processing. It includes
237
+ functions for validation, transformation, and analysis.
243
238
 
244
- Attributes:
245
- DEFAULT_TIMEOUT (int): Default timeout value in seconds.
239
+ Attributes:
240
+ DEFAULT_TIMEOUT (int): Default timeout value in seconds.
246
241
 
247
- MAX_RETRIES (int): Maximum number of retry attempts.
242
+ MAX_RETRIES (int): Maximum number of retry attempts.
248
243
 
249
- Todo:
250
- * Add caching functionality
251
- * Improve error messages
252
- """
244
+ Todo:
245
+ * Add caching functionality
246
+ * Improve error messages
247
+ """
253
248
 
249
+ default_timeout = 30
254
250
 
255
- default_timeout = 30
251
+ max_retries = 3
256
252
 
257
- max_retries = 3
258
-
259
- def process_data():
260
- pass
253
+ def process_data():
254
+ pass
261
255
 
262
256
 
263
- `
264
- });
257
+ `);
265
258
  });
266
259
  it("renders source file without documentation correctly", () => {
267
260
  const content = _$createComponent(py.SourceFile, {
268
- path: "simple.py",
261
+ path: "test.py",
269
262
  get children() {
270
263
  return _$createComponent(py.FunctionDeclaration, {
271
264
  name: "hello_world",
@@ -273,16 +266,905 @@ it("renders source file without documentation correctly", () => {
273
266
  });
274
267
  }
275
268
  });
276
- const res = toSourceTextMultiple([content]);
277
- const file = res.contents.find(f => f.kind === "file" && f.path === "simple.py");
278
- expect(file).toBeDefined();
279
- assertFileContents(res, {
280
- "simple.py": d`
281
- def hello_world():
282
- print("Hello, World!")
269
+ expect(toSourceText(content)).toRenderTo(d`
270
+ def hello_world():
271
+ print("Hello, World!")
272
+
273
+
274
+ `);
275
+ });
276
+ it("nothing before top-level definition", () => {
277
+ const content = _$createComponent(py.SourceFile, {
278
+ path: "test.py",
279
+ get children() {
280
+ return _$createComponent(py.FunctionDeclaration, {
281
+ name: "hello",
282
+ children: "pass"
283
+ });
284
+ }
285
+ });
286
+ expect(toSourceText(content)).toRenderTo(d`
287
+ def hello():
288
+ pass
289
+
290
+
291
+ `);
292
+ });
293
+ it("nothing before non-definition", () => {
294
+ const content = _$createComponent(py.SourceFile, {
295
+ path: "test.py",
296
+ get children() {
297
+ return _$createComponent(py.VariableDeclaration, {
298
+ name: "x",
299
+ initializer: 42
300
+ });
301
+ }
302
+ });
303
+ expect(toSourceText(content)).toRenderTo("x = 42");
304
+ });
305
+ it("only doc before definition", () => {
306
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
307
+ get description() {
308
+ return [_$createComponent(Prose, {
309
+ children: "Module description."
310
+ })];
311
+ }
312
+ });
313
+ const content = _$createComponent(py.SourceFile, {
314
+ path: "test.py",
315
+ doc: moduleDoc,
316
+ get children() {
317
+ return _$createComponent(py.FunctionDeclaration, {
318
+ name: "hello",
319
+ children: "pass"
320
+ });
321
+ }
322
+ });
323
+ expect(toSourceText(content)).toRenderTo(d`
324
+ """
325
+ Module description.
326
+ """
327
+
328
+
329
+ def hello():
330
+ pass
331
+
332
+
333
+ `);
334
+ });
335
+ it("only doc before non-definition", () => {
336
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
337
+ get description() {
338
+ return [_$createComponent(Prose, {
339
+ children: "Module description."
340
+ })];
341
+ }
342
+ });
343
+ const content = _$createComponent(py.SourceFile, {
344
+ path: "test.py",
345
+ doc: moduleDoc,
346
+ get children() {
347
+ return _$createComponent(py.VariableDeclaration, {
348
+ name: "x",
349
+ initializer: 42
350
+ });
351
+ }
352
+ });
353
+ expect(toSourceText(content)).toRenderTo(d`
354
+ """
355
+ Module description.
356
+ """
357
+
358
+ x = 42`);
359
+ });
360
+ it("only header before definition", () => {
361
+ const content = _$createComponent(py.SourceFile, {
362
+ path: "test.py",
363
+ header: "#!/usr/bin/env python3",
364
+ get children() {
365
+ return _$createComponent(py.FunctionDeclaration, {
366
+ name: "hello",
367
+ children: "pass"
368
+ });
369
+ }
370
+ });
371
+
372
+ // 2 blank lines before definition (PEP 8)
373
+ expect(toSourceText(content)).toRenderTo(d`
374
+ #!/usr/bin/env python3
375
+
376
+
377
+ def hello():
378
+ pass
379
+
380
+
381
+ `);
382
+ });
383
+ it("only header before non-definition", () => {
384
+ const content = _$createComponent(py.SourceFile, {
385
+ path: "test.py",
386
+ header: "#!/usr/bin/env python3",
387
+ get children() {
388
+ return _$createComponent(py.VariableDeclaration, {
389
+ name: "x",
390
+ initializer: 42
391
+ });
392
+ }
393
+ });
394
+
395
+ // 1 blank line for non-definition
396
+ expect(toSourceText(content)).toRenderTo(d`
397
+ #!/usr/bin/env python3
398
+
399
+ x = 42`);
400
+ });
401
+ it("only futureImports before definition", () => {
402
+ const content = _$createComponent(py.SourceFile, {
403
+ path: "test.py",
404
+ get futureImports() {
405
+ return _$createComponent(py.FutureStatement, {
406
+ feature: "annotations"
407
+ });
408
+ },
409
+ get children() {
410
+ return _$createComponent(py.FunctionDeclaration, {
411
+ name: "hello",
412
+ children: "pass"
413
+ });
414
+ }
415
+ });
416
+ expect(toSourceText(content)).toRenderTo(d`
417
+ from __future__ import annotations
418
+
419
+
420
+ def hello():
421
+ pass
422
+
423
+
424
+ `);
425
+ });
426
+ it("only futureImports before non-definition", () => {
427
+ const content = _$createComponent(py.SourceFile, {
428
+ path: "test.py",
429
+ get futureImports() {
430
+ return _$createComponent(py.FutureStatement, {
431
+ feature: "annotations"
432
+ });
433
+ },
434
+ get children() {
435
+ return _$createComponent(py.VariableDeclaration, {
436
+ name: "x",
437
+ initializer: 42
438
+ });
439
+ }
440
+ });
441
+ expect(toSourceText(content)).toRenderTo(d`
442
+ from __future__ import annotations
443
+
444
+ x = 42`);
445
+ });
446
+ it("only imports before definition", () => {
447
+ const content = _$createComponent(py.SourceFile, {
448
+ path: "test.py",
449
+ get children() {
450
+ return _$createComponent(py.DataclassDeclaration, {
451
+ name: "User",
452
+ get children() {
453
+ return _$createComponent(py.VariableDeclaration, {
454
+ name: "name",
455
+ type: "str"
456
+ });
457
+ }
458
+ });
459
+ }
460
+ });
461
+ expect(toSourceText(content, {
462
+ externals: [dataclassesModule]
463
+ })).toRenderTo(d`
464
+ from dataclasses import dataclass
465
+
466
+
467
+ @dataclass
468
+ class User:
469
+ name: str = None
470
+
471
+
472
+ `);
473
+ });
474
+ it("only imports before non-definition", () => {
475
+ const content = _$createComponent(py.SourceFile, {
476
+ path: "test.py",
477
+ get children() {
478
+ return _$createComponent(py.VariableDeclaration, {
479
+ name: "x",
480
+ get initializer() {
481
+ return _$createComponent(py.Reference, {
482
+ get refkey() {
483
+ return dataclassesModule["."].dataclass;
484
+ }
485
+ });
486
+ }
487
+ });
488
+ }
489
+ });
490
+ expect(toSourceText(content, {
491
+ externals: [dataclassesModule]
492
+ })).toRenderTo(d`
493
+ from dataclasses import dataclass
494
+
495
+ x = dataclass`);
496
+ });
497
+ it("doc + futureImports before definition", () => {
498
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
499
+ get description() {
500
+ return [_$createComponent(Prose, {
501
+ children: "Module description."
502
+ })];
503
+ }
504
+ });
505
+ const content = _$createComponent(py.SourceFile, {
506
+ path: "test.py",
507
+ doc: moduleDoc,
508
+ get futureImports() {
509
+ return _$createComponent(py.FutureStatement, {
510
+ feature: "annotations"
511
+ });
512
+ },
513
+ get children() {
514
+ return _$createComponent(py.FunctionDeclaration, {
515
+ name: "hello",
516
+ children: "pass"
517
+ });
518
+ }
519
+ });
520
+ expect(toSourceText(content)).toRenderTo(d`
521
+ """
522
+ Module description.
523
+ """
524
+
525
+ from __future__ import annotations
526
+
527
+
528
+ def hello():
529
+ pass
530
+
531
+
532
+ `);
533
+ });
534
+ it("doc + futureImports before non-definition", () => {
535
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
536
+ get description() {
537
+ return [_$createComponent(Prose, {
538
+ children: "Module description."
539
+ })];
540
+ }
541
+ });
542
+ const content = _$createComponent(py.SourceFile, {
543
+ path: "test.py",
544
+ doc: moduleDoc,
545
+ get futureImports() {
546
+ return _$createComponent(py.FutureStatement, {
547
+ feature: "annotations"
548
+ });
549
+ },
550
+ get children() {
551
+ return _$createComponent(py.VariableDeclaration, {
552
+ name: "x",
553
+ initializer: 42
554
+ });
555
+ }
556
+ });
557
+ expect(toSourceText(content)).toRenderTo(d`
558
+ """
559
+ Module description.
560
+ """
561
+
562
+ from __future__ import annotations
563
+
564
+ x = 42`);
565
+ });
566
+ it("doc + imports before definition", () => {
567
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
568
+ get description() {
569
+ return [_$createComponent(Prose, {
570
+ children: "Module description."
571
+ })];
572
+ }
573
+ });
574
+ const content = _$createComponent(py.SourceFile, {
575
+ path: "test.py",
576
+ doc: moduleDoc,
577
+ get children() {
578
+ return _$createComponent(py.DataclassDeclaration, {
579
+ name: "User",
580
+ get children() {
581
+ return _$createComponent(py.VariableDeclaration, {
582
+ name: "name",
583
+ type: "str"
584
+ });
585
+ }
586
+ });
587
+ }
588
+ });
589
+ expect(toSourceText(content, {
590
+ externals: [dataclassesModule]
591
+ })).toRenderTo(d`
592
+ """
593
+ Module description.
594
+ """
595
+
596
+ from dataclasses import dataclass
597
+
598
+
599
+ @dataclass
600
+ class User:
601
+ name: str = None
602
+
603
+
604
+ `);
605
+ });
606
+ it("doc + imports before non-definition", () => {
607
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
608
+ get description() {
609
+ return [_$createComponent(Prose, {
610
+ children: "Module description."
611
+ })];
612
+ }
613
+ });
614
+ const content = _$createComponent(py.SourceFile, {
615
+ path: "test.py",
616
+ doc: moduleDoc,
617
+ get children() {
618
+ return _$createComponent(py.VariableDeclaration, {
619
+ name: "x",
620
+ get initializer() {
621
+ return _$createComponent(py.Reference, {
622
+ get refkey() {
623
+ return dataclassesModule["."].dataclass;
624
+ }
625
+ });
626
+ }
627
+ });
628
+ }
629
+ });
630
+ expect(toSourceText(content, {
631
+ externals: [dataclassesModule]
632
+ })).toRenderTo(d`
633
+ """
634
+ Module description.
635
+ """
636
+
637
+ from dataclasses import dataclass
638
+
639
+ x = dataclass`);
640
+ });
641
+ it("futureImports + imports before definition", () => {
642
+ const content = _$createComponent(py.SourceFile, {
643
+ path: "test.py",
644
+ get futureImports() {
645
+ return _$createComponent(py.FutureStatement, {
646
+ feature: "annotations"
647
+ });
648
+ },
649
+ get children() {
650
+ return _$createComponent(py.DataclassDeclaration, {
651
+ name: "User",
652
+ get children() {
653
+ return _$createComponent(py.VariableDeclaration, {
654
+ name: "name",
655
+ type: "str"
656
+ });
657
+ }
658
+ });
659
+ }
660
+ });
661
+ expect(toSourceText(content, {
662
+ externals: [dataclassesModule]
663
+ })).toRenderTo(d`
664
+ from __future__ import annotations
665
+
666
+ from dataclasses import dataclass
667
+
668
+
669
+ @dataclass
670
+ class User:
671
+ name: str = None
672
+
673
+
674
+ `);
675
+ });
676
+ it("futureImports + imports before non-definition", () => {
677
+ const content = _$createComponent(py.SourceFile, {
678
+ path: "test.py",
679
+ get futureImports() {
680
+ return _$createComponent(py.FutureStatement, {
681
+ feature: "annotations"
682
+ });
683
+ },
684
+ get children() {
685
+ return _$createComponent(py.VariableDeclaration, {
686
+ name: "x",
687
+ get initializer() {
688
+ return _$createComponent(py.Reference, {
689
+ get refkey() {
690
+ return dataclassesModule["."].dataclass;
691
+ }
692
+ });
693
+ }
694
+ });
695
+ }
696
+ });
697
+ expect(toSourceText(content, {
698
+ externals: [dataclassesModule]
699
+ })).toRenderTo(d`
700
+ from __future__ import annotations
701
+
702
+ from dataclasses import dataclass
703
+
704
+ x = dataclass`);
705
+ });
706
+ it("doc + futureImports + imports before definition", () => {
707
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
708
+ get description() {
709
+ return [_$createComponent(Prose, {
710
+ children: "Module description."
711
+ })];
712
+ }
713
+ });
714
+ const content = _$createComponent(py.SourceFile, {
715
+ path: "test.py",
716
+ doc: moduleDoc,
717
+ get futureImports() {
718
+ return _$createComponent(py.FutureStatement, {
719
+ feature: "annotations"
720
+ });
721
+ },
722
+ get children() {
723
+ return _$createComponent(py.DataclassDeclaration, {
724
+ name: "User",
725
+ get children() {
726
+ return _$createComponent(py.VariableDeclaration, {
727
+ name: "name",
728
+ type: "str"
729
+ });
730
+ }
731
+ });
732
+ }
733
+ });
734
+ expect(toSourceText(content, {
735
+ externals: [dataclassesModule]
736
+ })).toRenderTo(d`
737
+ """
738
+ Module description.
739
+ """
740
+
741
+ from __future__ import annotations
742
+
743
+ from dataclasses import dataclass
744
+
745
+
746
+ @dataclass
747
+ class User:
748
+ name: str = None
749
+
750
+
751
+ `);
752
+ });
753
+ it("doc + futureImports + imports before non-definition", () => {
754
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
755
+ get description() {
756
+ return [_$createComponent(Prose, {
757
+ children: "Module description."
758
+ })];
759
+ }
760
+ });
761
+ const content = _$createComponent(py.SourceFile, {
762
+ path: "test.py",
763
+ doc: moduleDoc,
764
+ get futureImports() {
765
+ return _$createComponent(py.FutureStatement, {
766
+ feature: "annotations"
767
+ });
768
+ },
769
+ get children() {
770
+ return _$createComponent(py.VariableDeclaration, {
771
+ name: "x",
772
+ get initializer() {
773
+ return _$createComponent(py.Reference, {
774
+ get refkey() {
775
+ return dataclassesModule["."].dataclass;
776
+ }
777
+ });
778
+ }
779
+ });
780
+ }
781
+ });
782
+ expect(toSourceText(content, {
783
+ externals: [dataclassesModule]
784
+ })).toRenderTo(d`
785
+ """
786
+ Module description.
787
+ """
788
+
789
+ from __future__ import annotations
790
+
791
+ from dataclasses import dataclass
792
+
793
+ x = dataclass`);
794
+ });
795
+ it("only doc in file (no children)", () => {
796
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
797
+ get description() {
798
+ return [_$createComponent(Prose, {
799
+ children: "Module description."
800
+ })];
801
+ }
802
+ });
803
+ const content = _$createComponent(py.SourceFile, {
804
+ path: "test.py",
805
+ doc: moduleDoc
806
+ });
807
+ expect(toSourceText(content)).toRenderTo(d`
808
+ """
809
+ Module description.
810
+ """
811
+
812
+
813
+ `);
814
+ });
815
+ it("only header in file (no children)", () => {
816
+ const content = _$createComponent(py.SourceFile, {
817
+ path: "test.py",
818
+ header: "#!/usr/bin/env python3"
819
+ });
820
+ expect(toSourceText(content)).toRenderTo(d`
821
+ #!/usr/bin/env python3
822
+
823
+
824
+ `);
825
+ });
826
+ it("only futureImports in file (no children)", () => {
827
+ const content = _$createComponent(py.SourceFile, {
828
+ path: "test.py",
829
+ get futureImports() {
830
+ return _$createComponent(py.FutureStatement, {
831
+ feature: "annotations"
832
+ });
833
+ }
834
+ });
835
+ expect(toSourceText(content)).toRenderTo(d`
836
+ from __future__ import annotations
837
+
838
+ `);
839
+ });
840
+ it("doc + futureImports in file (no children)", () => {
841
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
842
+ get description() {
843
+ return [_$createComponent(Prose, {
844
+ children: "Module description."
845
+ })];
846
+ }
847
+ });
848
+ const content = _$createComponent(py.SourceFile, {
849
+ path: "test.py",
850
+ doc: moduleDoc,
851
+ get futureImports() {
852
+ return _$createComponent(py.FutureStatement, {
853
+ feature: "annotations"
854
+ });
855
+ }
856
+ });
857
+ expect(toSourceText(content)).toRenderTo(d`
858
+ """
859
+ Module description.
860
+ """
861
+
862
+ from __future__ import annotations
863
+
864
+ `);
865
+ });
866
+
867
+ // headerComment tests
868
+ it("only headerComment before definition", () => {
869
+ const content = _$createComponent(py.SourceFile, {
870
+ path: "test.py",
871
+ headerComment: "Copyright 2024 My Company",
872
+ get children() {
873
+ return _$createComponent(py.FunctionDeclaration, {
874
+ name: "hello",
875
+ children: "pass"
876
+ });
877
+ }
878
+ });
879
+
880
+ // 2 blank lines before definition (PEP 8)
881
+ expect(toSourceText(content)).toRenderTo(d`
882
+ # Copyright 2024 My Company
883
+
884
+
885
+ def hello():
886
+ pass
887
+
888
+
889
+ `);
890
+ });
891
+ it("only headerComment before non-definition", () => {
892
+ const content = _$createComponent(py.SourceFile, {
893
+ path: "test.py",
894
+ headerComment: "Copyright 2024 My Company",
895
+ get children() {
896
+ return _$createComponent(py.VariableDeclaration, {
897
+ name: "x",
898
+ initializer: 42
899
+ });
900
+ }
901
+ });
902
+ expect(toSourceText(content)).toRenderTo(d`
903
+ # Copyright 2024 My Company
904
+
905
+ x = 42`);
906
+ });
907
+ it("headerComment + doc before definition", () => {
908
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
909
+ get description() {
910
+ return [_$createComponent(Prose, {
911
+ children: "Module description."
912
+ })];
913
+ }
914
+ });
915
+ const content = _$createComponent(py.SourceFile, {
916
+ path: "test.py",
917
+ headerComment: "Copyright 2024 My Company",
918
+ doc: moduleDoc,
919
+ get children() {
920
+ return _$createComponent(py.FunctionDeclaration, {
921
+ name: "hello",
922
+ children: "pass"
923
+ });
924
+ }
925
+ });
283
926
 
927
+ // headerComment and doc adjacent, then PEP 8 spacing before definition
928
+ expect(toSourceText(content)).toRenderTo(d`
929
+ # Copyright 2024 My Company
930
+ """
931
+ Module description.
932
+ """
284
933
 
285
- `
934
+
935
+ def hello():
936
+ pass
937
+
938
+
939
+ `);
940
+ });
941
+ it("headerComment + futureImports before definition", () => {
942
+ const content = _$createComponent(py.SourceFile, {
943
+ path: "test.py",
944
+ headerComment: "Copyright 2024 My Company",
945
+ get futureImports() {
946
+ return _$createComponent(py.FutureStatement, {
947
+ feature: "annotations"
948
+ });
949
+ },
950
+ get children() {
951
+ return _$createComponent(py.FunctionDeclaration, {
952
+ name: "hello",
953
+ children: "pass"
954
+ });
955
+ }
956
+ });
957
+
958
+ // headerComment and futureImports adjacent, then PEP 8 spacing
959
+ expect(toSourceText(content)).toRenderTo(d`
960
+ # Copyright 2024 My Company
961
+
962
+ from __future__ import annotations
963
+
964
+
965
+ def hello():
966
+ pass
967
+
968
+
969
+ `);
970
+ });
971
+ it("headerComment + imports before definition", () => {
972
+ const content = _$createComponent(py.SourceFile, {
973
+ path: "test.py",
974
+ headerComment: "Copyright 2024 My Company",
975
+ get children() {
976
+ return _$createComponent(py.DataclassDeclaration, {
977
+ name: "User",
978
+ get children() {
979
+ return _$createComponent(py.VariableDeclaration, {
980
+ name: "name",
981
+ type: "str"
982
+ });
983
+ }
984
+ });
985
+ }
986
+ });
987
+ expect(toSourceText(content, {
988
+ externals: [dataclassesModule]
989
+ })).toRenderTo(d`
990
+ # Copyright 2024 My Company
991
+
992
+ from dataclasses import dataclass
993
+
994
+
995
+ @dataclass
996
+ class User:
997
+ name: str = None
998
+
999
+
1000
+ `);
1001
+ });
1002
+ it("headerComment + doc + futureImports before definition", () => {
1003
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
1004
+ get description() {
1005
+ return [_$createComponent(Prose, {
1006
+ children: "Module description."
1007
+ })];
1008
+ }
286
1009
  });
1010
+ const content = _$createComponent(py.SourceFile, {
1011
+ path: "test.py",
1012
+ headerComment: "Copyright 2024 My Company",
1013
+ doc: moduleDoc,
1014
+ get futureImports() {
1015
+ return _$createComponent(py.FutureStatement, {
1016
+ feature: "annotations"
1017
+ });
1018
+ },
1019
+ get children() {
1020
+ return _$createComponent(py.FunctionDeclaration, {
1021
+ name: "hello",
1022
+ children: "pass"
1023
+ });
1024
+ }
1025
+ });
1026
+ expect(toSourceText(content)).toRenderTo(d`
1027
+ # Copyright 2024 My Company
1028
+ """
1029
+ Module description.
1030
+ """
1031
+
1032
+ from __future__ import annotations
1033
+
1034
+
1035
+ def hello():
1036
+ pass
1037
+
1038
+
1039
+ `);
1040
+ });
1041
+ it("headerComment + doc + futureImports + imports before definition", () => {
1042
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
1043
+ get description() {
1044
+ return [_$createComponent(Prose, {
1045
+ children: "Module description."
1046
+ })];
1047
+ }
1048
+ });
1049
+ const content = _$createComponent(py.SourceFile, {
1050
+ path: "test.py",
1051
+ headerComment: "Copyright 2024 My Company",
1052
+ doc: moduleDoc,
1053
+ get futureImports() {
1054
+ return _$createComponent(py.FutureStatement, {
1055
+ feature: "annotations"
1056
+ });
1057
+ },
1058
+ get children() {
1059
+ return _$createComponent(py.DataclassDeclaration, {
1060
+ name: "User",
1061
+ get children() {
1062
+ return _$createComponent(py.VariableDeclaration, {
1063
+ name: "name",
1064
+ type: "str"
1065
+ });
1066
+ }
1067
+ });
1068
+ }
1069
+ });
1070
+ expect(toSourceText(content, {
1071
+ externals: [dataclassesModule]
1072
+ })).toRenderTo(d`
1073
+ # Copyright 2024 My Company
1074
+ """
1075
+ Module description.
1076
+ """
1077
+
1078
+ from __future__ import annotations
1079
+
1080
+ from dataclasses import dataclass
1081
+
1082
+
1083
+ @dataclass
1084
+ class User:
1085
+ name: str = None
1086
+
1087
+
1088
+ `);
1089
+ });
1090
+ it("only headerComment in file (no children)", () => {
1091
+ const content = _$createComponent(py.SourceFile, {
1092
+ path: "test.py",
1093
+ headerComment: "Copyright 2024 My Company"
1094
+ });
1095
+ expect(toSourceText(content)).toRenderTo(d`
1096
+ # Copyright 2024 My Company
1097
+
1098
+ `);
1099
+ });
1100
+ it("header + headerComment before definition", () => {
1101
+ const content = _$createComponent(py.SourceFile, {
1102
+ path: "test.py",
1103
+ header: "#!/usr/bin/env python3",
1104
+ headerComment: "Copyright 2024 My Company",
1105
+ get children() {
1106
+ return _$createComponent(py.FunctionDeclaration, {
1107
+ name: "hello",
1108
+ children: "pass"
1109
+ });
1110
+ }
1111
+ });
1112
+
1113
+ // 2 blank lines before definition (PEP 8)
1114
+ expect(toSourceText(content)).toRenderTo(d`
1115
+ #!/usr/bin/env python3
1116
+ # Copyright 2024 My Company
1117
+
1118
+
1119
+ def hello():
1120
+ pass
1121
+
1122
+
1123
+ `);
1124
+ });
1125
+ it("header + headerComment before class definition", () => {
1126
+ const content = _$createComponent(py.SourceFile, {
1127
+ path: "test.py",
1128
+ header: "#!/usr/bin/env python3",
1129
+ headerComment: "Copyright 2024 My Company",
1130
+ get children() {
1131
+ return _$createComponent(py.ClassDeclaration, {
1132
+ name: "MyClass",
1133
+ children: "pass"
1134
+ });
1135
+ }
1136
+ });
1137
+
1138
+ // 2 blank lines before definition (PEP 8)
1139
+ expect(toSourceText(content)).toRenderTo(d`
1140
+ #!/usr/bin/env python3
1141
+ # Copyright 2024 My Company
1142
+
1143
+
1144
+ class MyClass:
1145
+ pass
1146
+
1147
+
1148
+ `);
1149
+ });
1150
+ it("header + headerComment before non-definition", () => {
1151
+ const content = _$createComponent(py.SourceFile, {
1152
+ path: "test.py",
1153
+ header: "#!/usr/bin/env python3",
1154
+ headerComment: "Copyright 2024 My Company",
1155
+ get children() {
1156
+ return _$createComponent(py.VariableDeclaration, {
1157
+ name: "x",
1158
+ initializer: 42
1159
+ });
1160
+ }
1161
+ });
1162
+
1163
+ // 1 blank line for non-definition
1164
+ expect(toSourceText(content)).toRenderTo(d`
1165
+ #!/usr/bin/env python3
1166
+ # Copyright 2024 My Company
1167
+
1168
+ x = 42`);
287
1169
  });
288
1170
  //# sourceMappingURL=sourcefiles.test.js.map