@alloy-js/python 0.5.0-dev.1 → 0.5.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 (166) hide show
  1. package/dist/dev/src/components/SourceFile.js +44 -32
  2. package/dist/dev/src/components/SourceFile.js.map +1 -1
  3. package/dist/dev/test/callsignatures.test.js +471 -297
  4. package/dist/dev/test/callsignatures.test.js.map +1 -1
  5. package/dist/dev/test/class-method-declaration.test.js +21 -10
  6. package/dist/dev/test/class-method-declaration.test.js.map +1 -1
  7. package/dist/dev/test/classdeclarations.test.js +459 -393
  8. package/dist/dev/test/classdeclarations.test.js.map +1 -1
  9. package/dist/dev/test/classinstantiations.test.js +201 -168
  10. package/dist/dev/test/classinstantiations.test.js.map +1 -1
  11. package/dist/dev/test/constructordeclaration.test.js +22 -11
  12. package/dist/dev/test/constructordeclaration.test.js.map +1 -1
  13. package/dist/dev/test/dataclassdeclarations.test.js +322 -368
  14. package/dist/dev/test/dataclassdeclarations.test.js.map +1 -1
  15. package/dist/dev/test/decoratorlist.test.js +96 -49
  16. package/dist/dev/test/decoratorlist.test.js.map +1 -1
  17. package/dist/dev/test/dundermethoddeclaration.test.js +22 -11
  18. package/dist/dev/test/dundermethoddeclaration.test.js.map +1 -1
  19. package/dist/dev/test/enums.test.js +218 -184
  20. package/dist/dev/test/enums.test.js.map +1 -1
  21. package/dist/dev/test/externals.test.js +57 -45
  22. package/dist/dev/test/externals.test.js.map +1 -1
  23. package/dist/dev/test/factories.test.js +124 -50
  24. package/dist/dev/test/factories.test.js.map +1 -1
  25. package/dist/dev/test/functioncallexpressions.test.js +199 -164
  26. package/dist/dev/test/functioncallexpressions.test.js.map +1 -1
  27. package/dist/dev/test/functiondeclaration.test.js +439 -272
  28. package/dist/dev/test/functiondeclaration.test.js.map +1 -1
  29. package/dist/dev/test/imports.test.js +273 -221
  30. package/dist/dev/test/imports.test.js.map +1 -1
  31. package/dist/dev/test/memberexpressions.test.js +1237 -972
  32. package/dist/dev/test/memberexpressions.test.js.map +1 -1
  33. package/dist/dev/test/methoddeclaration.test.js +142 -78
  34. package/dist/dev/test/methoddeclaration.test.js.map +1 -1
  35. package/dist/dev/test/namepolicies.test.js +130 -94
  36. package/dist/dev/test/namepolicies.test.js.map +1 -1
  37. package/dist/dev/test/propertydeclaration.test.js +88 -59
  38. package/dist/dev/test/propertydeclaration.test.js.map +1 -1
  39. package/dist/dev/test/pydanticclassdeclarations.test.js +299 -347
  40. package/dist/dev/test/pydanticclassdeclarations.test.js.map +1 -1
  41. package/dist/dev/test/pydocs.test.js +888 -715
  42. package/dist/dev/test/pydocs.test.js.map +1 -1
  43. package/dist/dev/test/references.test.js +42 -35
  44. package/dist/dev/test/references.test.js.map +1 -1
  45. package/dist/dev/test/sourcefiles.test.js +1109 -841
  46. package/dist/dev/test/sourcefiles.test.js.map +1 -1
  47. package/dist/dev/test/staticmethoddeclaration.test.js +21 -10
  48. package/dist/dev/test/staticmethoddeclaration.test.js.map +1 -1
  49. package/dist/dev/test/type-checking-imports.test.js +408 -359
  50. package/dist/dev/test/type-checking-imports.test.js.map +1 -1
  51. package/dist/dev/test/typereference.test.js +55 -40
  52. package/dist/dev/test/typereference.test.js.map +1 -1
  53. package/dist/dev/test/uniontypeexpression.test.js +222 -146
  54. package/dist/dev/test/uniontypeexpression.test.js.map +1 -1
  55. package/dist/dev/test/utils.js +39 -77
  56. package/dist/dev/test/utils.js.map +1 -1
  57. package/dist/dev/test/values.test.js +237 -101
  58. package/dist/dev/test/values.test.js.map +1 -1
  59. package/dist/dev/test/variables.test.js +321 -203
  60. package/dist/dev/test/variables.test.js.map +1 -1
  61. package/dist/dev/test/vitest.setup.js +2 -0
  62. package/dist/dev/test/vitest.setup.js.map +1 -0
  63. package/dist/src/components/SourceFile.d.ts +2 -2
  64. package/dist/src/components/SourceFile.d.ts.map +1 -1
  65. package/dist/src/components/SourceFile.js +12 -0
  66. package/dist/src/components/SourceFile.js.map +1 -1
  67. package/dist/test/callsignatures.test.js +346 -272
  68. package/dist/test/callsignatures.test.js.map +1 -1
  69. package/dist/test/class-method-declaration.test.js +7 -4
  70. package/dist/test/class-method-declaration.test.js.map +1 -1
  71. package/dist/test/classdeclarations.test.js +302 -288
  72. package/dist/test/classdeclarations.test.js.map +1 -1
  73. package/dist/test/classinstantiations.test.js +112 -103
  74. package/dist/test/classinstantiations.test.js.map +1 -1
  75. package/dist/test/constructordeclaration.test.js +7 -4
  76. package/dist/test/constructordeclaration.test.js.map +1 -1
  77. package/dist/test/dataclassdeclarations.test.js +134 -184
  78. package/dist/test/dataclassdeclarations.test.js.map +1 -1
  79. package/dist/test/decoratorlist.test.js +59 -36
  80. package/dist/test/decoratorlist.test.js.map +1 -1
  81. package/dist/test/dundermethoddeclaration.test.js +7 -4
  82. package/dist/test/dundermethoddeclaration.test.js.map +1 -1
  83. package/dist/test/enums.test.js +161 -159
  84. package/dist/test/enums.test.js.map +1 -1
  85. package/dist/test/externals.test.js +24 -24
  86. package/dist/test/externals.test.js.map +1 -1
  87. package/dist/test/factories.test.js +75 -33
  88. package/dist/test/factories.test.js.map +1 -1
  89. package/dist/test/functioncallexpressions.test.js +117 -106
  90. package/dist/test/functioncallexpressions.test.js.map +1 -1
  91. package/dist/test/functiondeclaration.test.js +247 -180
  92. package/dist/test/functiondeclaration.test.js.map +1 -1
  93. package/dist/test/imports.test.js +171 -143
  94. package/dist/test/imports.test.js.map +1 -1
  95. package/dist/test/memberexpressions.test.js +582 -453
  96. package/dist/test/memberexpressions.test.js.map +1 -1
  97. package/dist/test/methoddeclaration.test.js +66 -46
  98. package/dist/test/methoddeclaration.test.js.map +1 -1
  99. package/dist/test/namepolicies.test.js +90 -78
  100. package/dist/test/namepolicies.test.js.map +1 -1
  101. package/dist/test/propertydeclaration.test.js +25 -20
  102. package/dist/test/propertydeclaration.test.js.map +1 -1
  103. package/dist/test/pydanticclassdeclarations.test.js +134 -190
  104. package/dist/test/pydanticclassdeclarations.test.js.map +1 -1
  105. package/dist/test/pydocs.test.js +573 -532
  106. package/dist/test/pydocs.test.js.map +1 -1
  107. package/dist/test/references.test.js +31 -28
  108. package/dist/test/references.test.js.map +1 -1
  109. package/dist/test/sourcefiles.test.js +700 -580
  110. package/dist/test/sourcefiles.test.js.map +1 -1
  111. package/dist/test/staticmethoddeclaration.test.js +7 -4
  112. package/dist/test/staticmethoddeclaration.test.js.map +1 -1
  113. package/dist/test/type-checking-imports.test.js +297 -284
  114. package/dist/test/type-checking-imports.test.js.map +1 -1
  115. package/dist/test/typereference.test.js +29 -22
  116. package/dist/test/typereference.test.js.map +1 -1
  117. package/dist/test/uniontypeexpression.test.js +124 -88
  118. package/dist/test/uniontypeexpression.test.js.map +1 -1
  119. package/dist/test/utils.d.ts +10 -17
  120. package/dist/test/utils.d.ts.map +1 -1
  121. package/dist/test/utils.js +32 -74
  122. package/dist/test/utils.js.map +1 -1
  123. package/dist/test/values.test.js +135 -67
  124. package/dist/test/values.test.js.map +1 -1
  125. package/dist/test/variables.test.js +201 -151
  126. package/dist/test/variables.test.js.map +1 -1
  127. package/dist/test/vitest.setup.d.ts +2 -0
  128. package/dist/test/vitest.setup.d.ts.map +1 -0
  129. package/dist/test/vitest.setup.js +2 -0
  130. package/dist/test/vitest.setup.js.map +1 -0
  131. package/dist/tsconfig.tsbuildinfo +1 -1
  132. package/docs/api/components/SourceFile.md +20 -8
  133. package/package.json +2 -2
  134. package/src/components/SourceFile.tsx +6 -1
  135. package/temp/api.json +16 -2
  136. package/test/callsignatures.test.tsx +309 -283
  137. package/test/class-method-declaration.test.tsx +3 -4
  138. package/test/classdeclarations.test.tsx +263 -248
  139. package/test/classinstantiations.test.tsx +115 -109
  140. package/test/constructordeclaration.test.tsx +9 -6
  141. package/test/dataclassdeclarations.test.tsx +243 -361
  142. package/test/decoratorlist.test.tsx +78 -59
  143. package/test/dundermethoddeclaration.test.tsx +3 -4
  144. package/test/enums.test.tsx +65 -81
  145. package/test/externals.test.tsx +25 -25
  146. package/test/factories.test.tsx +64 -22
  147. package/test/functioncallexpressions.test.tsx +123 -109
  148. package/test/functiondeclaration.test.tsx +209 -148
  149. package/test/imports.test.tsx +119 -91
  150. package/test/memberexpressions.test.tsx +265 -207
  151. package/test/methoddeclaration.test.tsx +84 -63
  152. package/test/namepolicies.test.tsx +69 -69
  153. package/test/propertydeclaration.test.tsx +7 -8
  154. package/test/pydanticclassdeclarations.test.tsx +355 -487
  155. package/test/pydocs.test.tsx +531 -579
  156. package/test/references.test.tsx +24 -23
  157. package/test/sourcefiles.test.tsx +527 -492
  158. package/test/staticmethoddeclaration.test.tsx +3 -4
  159. package/test/type-checking-imports.test.tsx +206 -218
  160. package/test/typereference.test.tsx +15 -12
  161. package/test/uniontypeexpression.test.tsx +74 -61
  162. package/test/utils.tsx +26 -110
  163. package/test/values.test.tsx +82 -32
  164. package/test/variables.test.tsx +162 -142
  165. package/test/vitest.setup.ts +1 -0
  166. package/vitest.config.ts +3 -0
@@ -1,7 +1,6 @@
1
- import { d } from "@alloy-js/core/testing";
2
1
  import { describe, expect, it } from "vitest";
3
2
  import * as py from "../src/index.js";
4
- import { toSourceText } from "./utils.js";
3
+ import { TestOutput } from "./utils.js";
5
4
 
6
5
  describe("StaticMethodDeclaration", () => {
7
6
  it("renders async static method", () => {
@@ -17,7 +16,7 @@ describe("StaticMethodDeclaration", () => {
17
16
  </py.StatementList>
18
17
  );
19
18
 
20
- expect(toSourceText([decl])).toBe(d`
19
+ expect(<TestOutput>{decl}</TestOutput>).toRenderTo(`
21
20
  class MyClass:
22
21
  @staticmethod
23
22
  async def util() -> str:
@@ -37,7 +36,7 @@ describe("StaticMethodDeclaration", () => {
37
36
  </py.ClassDeclaration>
38
37
  );
39
38
 
40
- expect(toSourceText([decl])).toBe(d`
39
+ expect(<TestOutput>{decl}</TestOutput>).toRenderTo(`
41
40
  class MyClass:
42
41
  @staticmethod
43
42
  def foo(x: int):
@@ -1,123 +1,121 @@
1
1
  import { refkey } from "@alloy-js/core";
2
- import { describe, it } from "vitest";
2
+ import { describe, expect, it } from "vitest";
3
3
  import { createModule } from "../src/create-module.js";
4
4
  import * as py from "../src/index.js";
5
- import { assertFileContents, toSourceTextMultiple } from "./utils.jsx";
5
+ import { TestOutputDirectory } from "./utils.js";
6
6
 
7
7
  describe("TYPE_CHECKING imports", () => {
8
8
  it("imports type-only references inside TYPE_CHECKING block", () => {
9
9
  const userClassRef = refkey();
10
10
 
11
- const result = toSourceTextMultiple([
12
- <py.SourceFile path="models.py">
13
- <py.ClassDeclaration name="User" refkey={userClassRef} />
14
- </py.SourceFile>,
15
- <py.SourceFile path="service.py">
16
- <py.FunctionDeclaration
17
- name="process_user"
18
- parameters={[{ name: "user", type: userClassRef }]}
19
- returnType="None"
20
- >
21
- pass
22
- </py.FunctionDeclaration>
23
- </py.SourceFile>,
24
- ]);
25
-
26
- assertFileContents(result, {
27
- "models.py": `
28
- class User:
11
+ expect(
12
+ <TestOutputDirectory>
13
+ <py.SourceFile path="models.py">
14
+ <py.ClassDeclaration name="User" refkey={userClassRef} />
15
+ </py.SourceFile>
16
+ <py.SourceFile path="service.py">
17
+ <py.FunctionDeclaration
18
+ name="process_user"
19
+ parameters={[{ name: "user", type: userClassRef }]}
20
+ returnType="None"
21
+ >
29
22
  pass
23
+ </py.FunctionDeclaration>
24
+ </py.SourceFile>
25
+ </TestOutputDirectory>,
26
+ ).toRenderTo({
27
+ "models.py": `
28
+ class User:
29
+ pass
30
30
 
31
- `,
31
+ `,
32
32
  "service.py": `
33
- from typing import TYPE_CHECKING
33
+ from typing import TYPE_CHECKING
34
34
 
35
- if TYPE_CHECKING:
36
- from models import User
35
+ if TYPE_CHECKING:
36
+ from models import User
37
37
 
38
38
 
39
- def process_user(user: User) -> None:
40
- pass
39
+ def process_user(user: User) -> None:
40
+ pass
41
41
 
42
- `,
42
+ `,
43
43
  });
44
44
  });
45
45
 
46
46
  it("imports value references outside TYPE_CHECKING block", () => {
47
47
  const userClassRef = refkey();
48
48
 
49
- const result = toSourceTextMultiple([
50
- <py.SourceFile path="models.py">
51
- <py.ClassDeclaration name="User" refkey={userClassRef} />
52
- </py.SourceFile>,
53
- <py.SourceFile path="service.py">
54
- <py.FunctionDeclaration name="create_user" returnType="None">
55
- <py.VariableDeclaration
56
- name="user"
57
- initializer={<py.ClassInstantiation target={userClassRef} />}
58
- />
59
- </py.FunctionDeclaration>
60
- </py.SourceFile>,
61
- ]);
62
-
63
- assertFileContents(result, {
49
+ expect(
50
+ <TestOutputDirectory>
51
+ <py.SourceFile path="models.py">
52
+ <py.ClassDeclaration name="User" refkey={userClassRef} />
53
+ </py.SourceFile>
54
+ <py.SourceFile path="service.py">
55
+ <py.FunctionDeclaration name="create_user" returnType="None">
56
+ <py.VariableDeclaration
57
+ name="user"
58
+ initializer={<py.ClassInstantiation target={userClassRef} />}
59
+ />
60
+ </py.FunctionDeclaration>
61
+ </py.SourceFile>
62
+ </TestOutputDirectory>,
63
+ ).toRenderTo({
64
64
  "models.py": `
65
- class User:
66
- pass
65
+ class User:
66
+ pass
67
67
 
68
- `,
68
+ `,
69
69
  "service.py": `
70
- from models import User
70
+ from models import User
71
71
 
72
72
 
73
- def create_user() -> None:
74
- user = User()
73
+ def create_user() -> None:
74
+ user = User()
75
75
 
76
- `,
76
+ `,
77
77
  });
78
78
  });
79
79
 
80
80
  it("upgrades type-only import to regular import when also used as value", () => {
81
81
  const userClassRef = refkey();
82
82
 
83
- const result = toSourceTextMultiple([
84
- <py.SourceFile path="models.py">
85
- <py.ClassDeclaration name="User" refkey={userClassRef} />
86
- </py.SourceFile>,
87
- <py.SourceFile path="service.py">
88
- <py.FunctionDeclaration
89
- name="create_user"
90
- parameters={[{ name: "existing", type: userClassRef }]}
91
- returnType={userClassRef}
92
- >
93
- <py.StatementList>
94
- <py.VariableDeclaration
95
- name="user"
96
- initializer={<py.ClassInstantiation target={userClassRef} />}
97
- />
98
- <>return user</>
99
- </py.StatementList>
100
- </py.FunctionDeclaration>
101
- </py.SourceFile>,
102
- ]);
103
-
104
- // Since User is used both as a type (parameter type, return type) and
105
- // as a value (ClassInstantiation), it should be a regular import
106
- assertFileContents(result, {
83
+ expect(
84
+ <TestOutputDirectory>
85
+ <py.SourceFile path="models.py">
86
+ <py.ClassDeclaration name="User" refkey={userClassRef} />
87
+ </py.SourceFile>
88
+ <py.SourceFile path="service.py">
89
+ <py.FunctionDeclaration
90
+ name="create_user"
91
+ parameters={[{ name: "existing", type: userClassRef }]}
92
+ returnType={userClassRef}
93
+ >
94
+ <py.StatementList>
95
+ <py.VariableDeclaration
96
+ name="user"
97
+ initializer={<py.ClassInstantiation target={userClassRef} />}
98
+ />
99
+ <>return user</>
100
+ </py.StatementList>
101
+ </py.FunctionDeclaration>
102
+ </py.SourceFile>
103
+ </TestOutputDirectory>,
104
+ ).toRenderTo({
107
105
  "models.py": `
108
- class User:
109
- pass
106
+ class User:
107
+ pass
110
108
 
111
- `,
109
+ `,
112
110
  "service.py": `
113
- from models import User
111
+ from models import User
114
112
 
115
113
 
116
- def create_user(existing: User) -> User:
117
- user = User()
118
- return user
114
+ def create_user(existing: User) -> User:
115
+ user = User()
116
+ return user
119
117
 
120
- `,
118
+ `,
121
119
  });
122
120
  });
123
121
 
@@ -125,179 +123,175 @@ describe("TYPE_CHECKING imports", () => {
125
123
  const userClassRef = refkey();
126
124
  const helperFuncRef = refkey();
127
125
 
128
- const result = toSourceTextMultiple([
129
- <py.SourceFile path="models.py">
130
- <py.ClassDeclaration name="User" refkey={userClassRef} />
131
- <py.FunctionDeclaration name="helper" refkey={helperFuncRef}>
132
- pass
133
- </py.FunctionDeclaration>
134
- </py.SourceFile>,
135
- <py.SourceFile path="service.py">
136
- <py.FunctionDeclaration
137
- name="process"
138
- parameters={[{ name: "user", type: userClassRef }]}
139
- returnType="None"
140
- >
141
- <py.FunctionCallExpression target={helperFuncRef} />
142
- </py.FunctionDeclaration>
143
- </py.SourceFile>,
144
- ]);
145
-
146
- // helper is used as a value (function call), User is only used as type
147
- assertFileContents(result, {
148
- "models.py": `
149
- class User:
126
+ expect(
127
+ <TestOutputDirectory>
128
+ <py.SourceFile path="models.py">
129
+ <py.ClassDeclaration name="User" refkey={userClassRef} />
130
+ <py.FunctionDeclaration name="helper" refkey={helperFuncRef}>
150
131
  pass
132
+ </py.FunctionDeclaration>
133
+ </py.SourceFile>
134
+ <py.SourceFile path="service.py">
135
+ <py.FunctionDeclaration
136
+ name="process"
137
+ parameters={[{ name: "user", type: userClassRef }]}
138
+ returnType="None"
139
+ >
140
+ <py.FunctionCallExpression target={helperFuncRef} />
141
+ </py.FunctionDeclaration>
142
+ </py.SourceFile>
143
+ </TestOutputDirectory>,
144
+ ).toRenderTo({
145
+ "models.py": `
146
+ class User:
147
+ pass
151
148
 
152
149
 
153
- def helper():
154
- pass
150
+ def helper():
151
+ pass
155
152
 
156
- `,
153
+ `,
157
154
  "service.py": `
158
- from models import helper
159
- from typing import TYPE_CHECKING
155
+ from models import helper
156
+ from typing import TYPE_CHECKING
160
157
 
161
- if TYPE_CHECKING:
162
- from models import User
158
+ if TYPE_CHECKING:
159
+ from models import User
163
160
 
164
161
 
165
- def process(user: User) -> None:
166
- helper()
162
+ def process(user: User) -> None:
163
+ helper()
167
164
 
168
- `,
165
+ `,
169
166
  });
170
167
  });
171
168
 
172
169
  it("handles return type as type-only import", () => {
173
170
  const resultTypeRef = refkey();
174
171
 
175
- const result = toSourceTextMultiple([
176
- <py.SourceFile path="types.py">
177
- <py.ClassDeclaration name="Result" refkey={resultTypeRef} />
178
- </py.SourceFile>,
179
- <py.SourceFile path="main.py">
180
- <py.FunctionDeclaration name="get_result" returnType={resultTypeRef}>
181
- pass
182
- </py.FunctionDeclaration>
183
- </py.SourceFile>,
184
- ]);
185
-
186
- assertFileContents(result, {
187
- "types.py": `
188
- class Result:
172
+ expect(
173
+ <TestOutputDirectory>
174
+ <py.SourceFile path="types.py">
175
+ <py.ClassDeclaration name="Result" refkey={resultTypeRef} />
176
+ </py.SourceFile>
177
+ <py.SourceFile path="main.py">
178
+ <py.FunctionDeclaration name="get_result" returnType={resultTypeRef}>
189
179
  pass
180
+ </py.FunctionDeclaration>
181
+ </py.SourceFile>
182
+ </TestOutputDirectory>,
183
+ ).toRenderTo({
184
+ "types.py": `
185
+ class Result:
186
+ pass
190
187
 
191
- `,
188
+ `,
192
189
  "main.py": `
193
- from typing import TYPE_CHECKING
190
+ from typing import TYPE_CHECKING
194
191
 
195
- if TYPE_CHECKING:
196
- from types import Result
192
+ if TYPE_CHECKING:
193
+ from types import Result
197
194
 
198
195
 
199
- def get_result() -> Result:
200
- pass
196
+ def get_result() -> Result:
197
+ pass
201
198
 
202
- `,
199
+ `,
203
200
  });
204
201
  });
205
202
 
206
203
  it("handles variable type annotation as type-only import", () => {
207
204
  const configTypeRef = refkey();
208
205
 
209
- const result = toSourceTextMultiple([
210
- <py.SourceFile path="types.py">
211
- <py.ClassDeclaration name="Config" refkey={configTypeRef} />
212
- </py.SourceFile>,
213
- <py.SourceFile path="main.py">
214
- <py.VariableDeclaration name="config" type={configTypeRef} omitNone />
215
- </py.SourceFile>,
216
- ]);
217
-
218
- assertFileContents(result, {
206
+ expect(
207
+ <TestOutputDirectory>
208
+ <py.SourceFile path="types.py">
209
+ <py.ClassDeclaration name="Config" refkey={configTypeRef} />
210
+ </py.SourceFile>
211
+ <py.SourceFile path="main.py">
212
+ <py.VariableDeclaration name="config" type={configTypeRef} omitNone />
213
+ </py.SourceFile>
214
+ </TestOutputDirectory>,
215
+ ).toRenderTo({
219
216
  "types.py": `
220
- class Config:
221
- pass
217
+ class Config:
218
+ pass
222
219
 
223
- `,
220
+ `,
224
221
  "main.py": `
225
- from typing import TYPE_CHECKING
222
+ from typing import TYPE_CHECKING
226
223
 
227
- if TYPE_CHECKING:
228
- from types import Config
224
+ if TYPE_CHECKING:
225
+ from types import Config
229
226
 
230
- config: Config
231
- `,
227
+ config: Config
228
+ `,
232
229
  });
233
230
  });
234
231
 
235
232
  it("handles TypeReference component as type-only import", () => {
236
233
  const myTypeRef = refkey();
237
234
 
238
- const result = toSourceTextMultiple([
239
- <py.SourceFile path="types.py">
240
- <py.ClassDeclaration name="MyType" refkey={myTypeRef} />
241
- </py.SourceFile>,
242
- <py.SourceFile path="main.py">
243
- <py.VariableDeclaration
244
- name="value"
245
- type={<py.TypeReference refkey={myTypeRef} />}
246
- omitNone
247
- />
248
- </py.SourceFile>,
249
- ]);
250
-
251
- assertFileContents(result, {
235
+ expect(
236
+ <TestOutputDirectory>
237
+ <py.SourceFile path="types.py">
238
+ <py.ClassDeclaration name="MyType" refkey={myTypeRef} />
239
+ </py.SourceFile>
240
+ <py.SourceFile path="main.py">
241
+ <py.VariableDeclaration
242
+ name="value"
243
+ type={<py.TypeReference refkey={myTypeRef} />}
244
+ omitNone
245
+ />
246
+ </py.SourceFile>
247
+ </TestOutputDirectory>,
248
+ ).toRenderTo({
252
249
  "types.py": `
253
- class MyType:
254
- pass
250
+ class MyType:
251
+ pass
255
252
 
256
- `,
253
+ `,
257
254
  "main.py": `
258
- from typing import TYPE_CHECKING
255
+ from typing import TYPE_CHECKING
259
256
 
260
- if TYPE_CHECKING:
261
- from types import MyType
257
+ if TYPE_CHECKING:
258
+ from types import MyType
262
259
 
263
- value: MyType
264
- `,
260
+ value: MyType
261
+ `,
265
262
  });
266
263
  });
267
264
 
268
265
  it("handles class bases as regular import (runtime requirement)", () => {
269
266
  const baseClassRef = refkey();
270
267
 
271
- const result = toSourceTextMultiple([
272
- <py.SourceFile path="base.py">
273
- <py.ClassDeclaration name="BaseClass" refkey={baseClassRef} />
274
- </py.SourceFile>,
275
- <py.SourceFile path="derived.py">
276
- <py.ClassDeclaration name="DerivedClass" bases={[baseClassRef]} />
277
- </py.SourceFile>,
278
- ]);
279
-
280
- // Class bases require runtime access, so they should NOT be
281
- // inside a TYPE_CHECKING block
282
- assertFileContents(result, {
268
+ expect(
269
+ <TestOutputDirectory>
270
+ <py.SourceFile path="base.py">
271
+ <py.ClassDeclaration name="BaseClass" refkey={baseClassRef} />
272
+ </py.SourceFile>
273
+ <py.SourceFile path="derived.py">
274
+ <py.ClassDeclaration name="DerivedClass" bases={[baseClassRef]} />
275
+ </py.SourceFile>
276
+ </TestOutputDirectory>,
277
+ ).toRenderTo({
283
278
  "base.py": `
284
- class BaseClass:
285
- pass
279
+ class BaseClass:
280
+ pass
286
281
 
287
- `,
282
+ `,
288
283
  "derived.py": `
289
- from base import BaseClass
284
+ from base import BaseClass
290
285
 
291
286
 
292
- class DerivedClass(BaseClass):
293
- pass
287
+ class DerivedClass(BaseClass):
288
+ pass
294
289
 
295
- `,
290
+ `,
296
291
  });
297
292
  });
298
293
 
299
294
  it("renders regular imports before TYPE_CHECKING block", () => {
300
- // Create a typing module with multiple exports
301
295
  const typingModule = createModule({
302
296
  name: "typing",
303
297
  descriptor: {
@@ -305,7 +299,6 @@ describe("TYPE_CHECKING imports", () => {
305
299
  },
306
300
  });
307
301
 
308
- // Create a third-party module
309
302
  const requestsModule = createModule({
310
303
  name: "requests",
311
304
  descriptor: {
@@ -315,11 +308,11 @@ describe("TYPE_CHECKING imports", () => {
315
308
 
316
309
  const userClassRef = refkey();
317
310
 
318
- const result = toSourceTextMultiple(
319
- [
311
+ expect(
312
+ <TestOutputDirectory externals={[typingModule, requestsModule]}>
320
313
  <py.SourceFile path="models.py">
321
314
  <py.ClassDeclaration name="User" refkey={userClassRef} />
322
- </py.SourceFile>,
315
+ </py.SourceFile>
323
316
  <py.SourceFile path="service.py">
324
317
  <py.FunctionDeclaration
325
318
  name="get_users"
@@ -327,37 +320,32 @@ describe("TYPE_CHECKING imports", () => {
327
320
  returnType="str"
328
321
  >
329
322
  <py.StatementList>
330
- {/* Use cast as a value (function call) to make it a regular import */}
331
323
  <>response = {requestsModule["."].get}("https://example.com")</>
332
324
  <>return {typingModule["."].cast}(str, user)</>
333
325
  </py.StatementList>
334
326
  </py.FunctionDeclaration>
335
- </py.SourceFile>,
336
- ],
337
- { externals: [typingModule, requestsModule] },
338
- );
339
-
340
- // Regular imports first (sorted alphabetically), then TYPE_CHECKING block
341
- assertFileContents(result, {
327
+ </py.SourceFile>
328
+ </TestOutputDirectory>,
329
+ ).toRenderTo({
342
330
  "models.py": `
343
- class User:
344
- pass
331
+ class User:
332
+ pass
345
333
 
346
- `,
334
+ `,
347
335
  "service.py": `
348
- from requests import get
349
- from typing import cast
350
- from typing import TYPE_CHECKING
336
+ from requests import get
337
+ from typing import cast
338
+ from typing import TYPE_CHECKING
351
339
 
352
- if TYPE_CHECKING:
353
- from models import User
340
+ if TYPE_CHECKING:
341
+ from models import User
354
342
 
355
343
 
356
- def get_users(user: User) -> str:
357
- response = get("https://example.com")
358
- return cast(str, user)
344
+ def get_users(user: User) -> str:
345
+ response = get("https://example.com")
346
+ return cast(str, user)
359
347
 
360
- `,
348
+ `,
361
349
  });
362
350
  });
363
351
  });
@@ -1,15 +1,14 @@
1
1
  import { code, refkey } from "@alloy-js/core";
2
- import { d } from "@alloy-js/core/testing";
3
2
  import { describe, expect, it } from "vitest";
4
3
  import * as py from "../src/index.js";
5
- import { toSourceText } from "./utils.jsx";
4
+ import { TestOutput } from "./utils.js";
6
5
 
7
6
  describe("TypeReference", () => {
8
7
  it("renders a Python TypeReference with a refkey and type arguments", () => {
9
8
  const classRefkey = refkey();
10
9
 
11
10
  expect(
12
- toSourceText([
11
+ <TestOutput>
13
12
  <py.StatementList>
14
13
  <py.ClassDeclaration
15
14
  name="Bar"
@@ -17,15 +16,17 @@ describe("TypeReference", () => {
17
16
  ></py.ClassDeclaration>
18
17
  <py.TypeReference refkey={classRefkey} typeArgs={["T", "P"]} />
19
18
  <py.TypeReference name="dict" typeArgs={["str", "int"]} />
20
- </py.StatementList>,
21
- ]),
22
- ).toRenderTo(d`
19
+ </py.StatementList>
20
+ </TestOutput>,
21
+ ).toRenderTo(
22
+ `
23
23
  class Bar:
24
24
  pass
25
25
 
26
26
  Bar[T, P]
27
27
  dict[str, int]
28
- `);
28
+ `,
29
+ );
29
30
  });
30
31
 
31
32
  it("renders a Python list expression with a reference", () => {
@@ -33,20 +34,22 @@ describe("TypeReference", () => {
33
34
  const type = code`list[${classRefkey}]`;
34
35
 
35
36
  expect(
36
- toSourceText([
37
+ <TestOutput>
37
38
  <py.StatementList>
38
39
  <py.ClassDeclaration
39
40
  name="Foo"
40
41
  refkey={classRefkey}
41
42
  ></py.ClassDeclaration>
42
43
  <py.TypeReference name={type} />
43
- </py.StatementList>,
44
- ]),
45
- ).toRenderTo(d`
44
+ </py.StatementList>
45
+ </TestOutput>,
46
+ ).toRenderTo(
47
+ `
46
48
  class Foo:
47
49
  pass
48
50
 
49
51
  list[Foo]
50
- `);
52
+ `,
53
+ );
51
54
  });
52
55
  });