@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,377 +1,390 @@
1
1
  import { createComponent as _$createComponent, memo as _$memo } from "@alloy-js/core/jsx-runtime";
2
2
  import { refkey } from "@alloy-js/core";
3
- import { describe, it } from "vitest";
3
+ import { describe, expect, it } from "vitest";
4
4
  import { createModule } from "../src/create-module.js";
5
5
  import * as py from "../src/index.js";
6
- import { assertFileContents, toSourceTextMultiple } from "./utils.js";
6
+ import { TestOutputDirectory } from "./utils.js";
7
7
  describe("TYPE_CHECKING imports", () => {
8
8
  it("imports type-only references inside TYPE_CHECKING block", () => {
9
9
  const userClassRef = refkey();
10
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
11
- path: "models.py",
10
+ expect(_$createComponent(TestOutputDirectory, {
12
11
  get children() {
13
- return _$createComponent(py.ClassDeclaration, {
14
- name: "User",
15
- refkey: userClassRef
16
- });
17
- }
18
- }), _$createComponent(py.SourceFile, {
19
- path: "service.py",
20
- get children() {
21
- return _$createComponent(py.FunctionDeclaration, {
22
- name: "process_user",
23
- parameters: [{
24
- name: "user",
25
- type: userClassRef
26
- }],
27
- returnType: "None",
28
- children: "pass"
29
- });
12
+ return [_$createComponent(py.SourceFile, {
13
+ path: "models.py",
14
+ get children() {
15
+ return _$createComponent(py.ClassDeclaration, {
16
+ name: "User",
17
+ refkey: userClassRef
18
+ });
19
+ }
20
+ }), _$createComponent(py.SourceFile, {
21
+ path: "service.py",
22
+ get children() {
23
+ return _$createComponent(py.FunctionDeclaration, {
24
+ name: "process_user",
25
+ parameters: [{
26
+ name: "user",
27
+ type: userClassRef
28
+ }],
29
+ returnType: "None",
30
+ children: "pass"
31
+ });
32
+ }
33
+ })];
30
34
  }
31
- })]);
32
- assertFileContents(result, {
35
+ })).toRenderTo({
33
36
  "models.py": `
34
- class User:
35
- pass
37
+ class User:
38
+ pass
36
39
 
37
- `,
40
+ `,
38
41
  "service.py": `
39
- from typing import TYPE_CHECKING
42
+ from typing import TYPE_CHECKING
40
43
 
41
- if TYPE_CHECKING:
42
- from models import User
44
+ if TYPE_CHECKING:
45
+ from models import User
43
46
 
44
47
 
45
- def process_user(user: User) -> None:
46
- pass
48
+ def process_user(user: User) -> None:
49
+ pass
47
50
 
48
- `
51
+ `
49
52
  });
50
53
  });
51
54
  it("imports value references outside TYPE_CHECKING block", () => {
52
55
  const userClassRef = refkey();
53
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
54
- path: "models.py",
56
+ expect(_$createComponent(TestOutputDirectory, {
55
57
  get children() {
56
- return _$createComponent(py.ClassDeclaration, {
57
- name: "User",
58
- refkey: userClassRef
59
- });
60
- }
61
- }), _$createComponent(py.SourceFile, {
62
- path: "service.py",
63
- get children() {
64
- return _$createComponent(py.FunctionDeclaration, {
65
- name: "create_user",
66
- returnType: "None",
58
+ return [_$createComponent(py.SourceFile, {
59
+ path: "models.py",
67
60
  get children() {
68
- return _$createComponent(py.VariableDeclaration, {
69
- name: "user",
70
- get initializer() {
71
- return _$createComponent(py.ClassInstantiation, {
72
- target: userClassRef
61
+ return _$createComponent(py.ClassDeclaration, {
62
+ name: "User",
63
+ refkey: userClassRef
64
+ });
65
+ }
66
+ }), _$createComponent(py.SourceFile, {
67
+ path: "service.py",
68
+ get children() {
69
+ return _$createComponent(py.FunctionDeclaration, {
70
+ name: "create_user",
71
+ returnType: "None",
72
+ get children() {
73
+ return _$createComponent(py.VariableDeclaration, {
74
+ name: "user",
75
+ get initializer() {
76
+ return _$createComponent(py.ClassInstantiation, {
77
+ target: userClassRef
78
+ });
79
+ }
73
80
  });
74
81
  }
75
82
  });
76
83
  }
77
- });
84
+ })];
78
85
  }
79
- })]);
80
- assertFileContents(result, {
86
+ })).toRenderTo({
81
87
  "models.py": `
82
- class User:
83
- pass
88
+ class User:
89
+ pass
84
90
 
85
- `,
91
+ `,
86
92
  "service.py": `
87
- from models import User
93
+ from models import User
88
94
 
89
95
 
90
- def create_user() -> None:
91
- user = User()
96
+ def create_user() -> None:
97
+ user = User()
92
98
 
93
- `
99
+ `
94
100
  });
95
101
  });
96
102
  it("upgrades type-only import to regular import when also used as value", () => {
97
103
  const userClassRef = refkey();
98
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
99
- path: "models.py",
100
- get children() {
101
- return _$createComponent(py.ClassDeclaration, {
102
- name: "User",
103
- refkey: userClassRef
104
- });
105
- }
106
- }), _$createComponent(py.SourceFile, {
107
- path: "service.py",
104
+ expect(_$createComponent(TestOutputDirectory, {
108
105
  get children() {
109
- return _$createComponent(py.FunctionDeclaration, {
110
- name: "create_user",
111
- parameters: [{
112
- name: "existing",
113
- type: userClassRef
114
- }],
115
- returnType: userClassRef,
106
+ return [_$createComponent(py.SourceFile, {
107
+ path: "models.py",
108
+ get children() {
109
+ return _$createComponent(py.ClassDeclaration, {
110
+ name: "User",
111
+ refkey: userClassRef
112
+ });
113
+ }
114
+ }), _$createComponent(py.SourceFile, {
115
+ path: "service.py",
116
116
  get children() {
117
- return _$createComponent(py.StatementList, {
117
+ return _$createComponent(py.FunctionDeclaration, {
118
+ name: "create_user",
119
+ parameters: [{
120
+ name: "existing",
121
+ type: userClassRef
122
+ }],
123
+ returnType: userClassRef,
118
124
  get children() {
119
- return [_$createComponent(py.VariableDeclaration, {
120
- name: "user",
121
- get initializer() {
122
- return _$createComponent(py.ClassInstantiation, {
123
- target: userClassRef
124
- });
125
+ return _$createComponent(py.StatementList, {
126
+ get children() {
127
+ return [_$createComponent(py.VariableDeclaration, {
128
+ name: "user",
129
+ get initializer() {
130
+ return _$createComponent(py.ClassInstantiation, {
131
+ target: userClassRef
132
+ });
133
+ }
134
+ }), ["return user"]];
125
135
  }
126
- }), ["return user"]];
136
+ });
127
137
  }
128
138
  });
129
139
  }
130
- });
140
+ })];
131
141
  }
132
- })]);
133
-
134
- // Since User is used both as a type (parameter type, return type) and
135
- // as a value (ClassInstantiation), it should be a regular import
136
- assertFileContents(result, {
142
+ })).toRenderTo({
137
143
  "models.py": `
138
- class User:
139
- pass
144
+ class User:
145
+ pass
140
146
 
141
- `,
147
+ `,
142
148
  "service.py": `
143
- from models import User
149
+ from models import User
144
150
 
145
151
 
146
- def create_user(existing: User) -> User:
147
- user = User()
148
- return user
152
+ def create_user(existing: User) -> User:
153
+ user = User()
154
+ return user
149
155
 
150
- `
156
+ `
151
157
  });
152
158
  });
153
159
  it("handles mixed type-only and regular imports from same module", () => {
154
160
  const userClassRef = refkey();
155
161
  const helperFuncRef = refkey();
156
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
157
- path: "models.py",
162
+ expect(_$createComponent(TestOutputDirectory, {
158
163
  get children() {
159
- return [_$createComponent(py.ClassDeclaration, {
160
- name: "User",
161
- refkey: userClassRef
162
- }), _$createComponent(py.FunctionDeclaration, {
163
- name: "helper",
164
- refkey: helperFuncRef,
165
- children: "pass"
166
- })];
167
- }
168
- }), _$createComponent(py.SourceFile, {
169
- path: "service.py",
170
- get children() {
171
- return _$createComponent(py.FunctionDeclaration, {
172
- name: "process",
173
- parameters: [{
174
- name: "user",
175
- type: userClassRef
176
- }],
177
- returnType: "None",
164
+ return [_$createComponent(py.SourceFile, {
165
+ path: "models.py",
178
166
  get children() {
179
- return _$createComponent(py.FunctionCallExpression, {
180
- target: helperFuncRef
167
+ return [_$createComponent(py.ClassDeclaration, {
168
+ name: "User",
169
+ refkey: userClassRef
170
+ }), _$createComponent(py.FunctionDeclaration, {
171
+ name: "helper",
172
+ refkey: helperFuncRef,
173
+ children: "pass"
174
+ })];
175
+ }
176
+ }), _$createComponent(py.SourceFile, {
177
+ path: "service.py",
178
+ get children() {
179
+ return _$createComponent(py.FunctionDeclaration, {
180
+ name: "process",
181
+ parameters: [{
182
+ name: "user",
183
+ type: userClassRef
184
+ }],
185
+ returnType: "None",
186
+ get children() {
187
+ return _$createComponent(py.FunctionCallExpression, {
188
+ target: helperFuncRef
189
+ });
190
+ }
181
191
  });
182
192
  }
183
- });
193
+ })];
184
194
  }
185
- })]);
186
-
187
- // helper is used as a value (function call), User is only used as type
188
- assertFileContents(result, {
195
+ })).toRenderTo({
189
196
  "models.py": `
190
- class User:
191
- pass
197
+ class User:
198
+ pass
192
199
 
193
200
 
194
- def helper():
195
- pass
201
+ def helper():
202
+ pass
196
203
 
197
- `,
204
+ `,
198
205
  "service.py": `
199
- from models import helper
200
- from typing import TYPE_CHECKING
206
+ from models import helper
207
+ from typing import TYPE_CHECKING
201
208
 
202
- if TYPE_CHECKING:
203
- from models import User
209
+ if TYPE_CHECKING:
210
+ from models import User
204
211
 
205
212
 
206
- def process(user: User) -> None:
207
- helper()
213
+ def process(user: User) -> None:
214
+ helper()
208
215
 
209
- `
216
+ `
210
217
  });
211
218
  });
212
219
  it("handles return type as type-only import", () => {
213
220
  const resultTypeRef = refkey();
214
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
215
- path: "types.py",
216
- get children() {
217
- return _$createComponent(py.ClassDeclaration, {
218
- name: "Result",
219
- refkey: resultTypeRef
220
- });
221
- }
222
- }), _$createComponent(py.SourceFile, {
223
- path: "main.py",
221
+ expect(_$createComponent(TestOutputDirectory, {
224
222
  get children() {
225
- return _$createComponent(py.FunctionDeclaration, {
226
- name: "get_result",
227
- returnType: resultTypeRef,
228
- children: "pass"
229
- });
223
+ return [_$createComponent(py.SourceFile, {
224
+ path: "types.py",
225
+ get children() {
226
+ return _$createComponent(py.ClassDeclaration, {
227
+ name: "Result",
228
+ refkey: resultTypeRef
229
+ });
230
+ }
231
+ }), _$createComponent(py.SourceFile, {
232
+ path: "main.py",
233
+ get children() {
234
+ return _$createComponent(py.FunctionDeclaration, {
235
+ name: "get_result",
236
+ returnType: resultTypeRef,
237
+ children: "pass"
238
+ });
239
+ }
240
+ })];
230
241
  }
231
- })]);
232
- assertFileContents(result, {
242
+ })).toRenderTo({
233
243
  "types.py": `
234
- class Result:
235
- pass
244
+ class Result:
245
+ pass
236
246
 
237
- `,
247
+ `,
238
248
  "main.py": `
239
- from typing import TYPE_CHECKING
249
+ from typing import TYPE_CHECKING
240
250
 
241
- if TYPE_CHECKING:
242
- from types import Result
251
+ if TYPE_CHECKING:
252
+ from types import Result
243
253
 
244
254
 
245
- def get_result() -> Result:
246
- pass
255
+ def get_result() -> Result:
256
+ pass
247
257
 
248
- `
258
+ `
249
259
  });
250
260
  });
251
261
  it("handles variable type annotation as type-only import", () => {
252
262
  const configTypeRef = refkey();
253
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
254
- path: "types.py",
255
- get children() {
256
- return _$createComponent(py.ClassDeclaration, {
257
- name: "Config",
258
- refkey: configTypeRef
259
- });
260
- }
261
- }), _$createComponent(py.SourceFile, {
262
- path: "main.py",
263
+ expect(_$createComponent(TestOutputDirectory, {
263
264
  get children() {
264
- return _$createComponent(py.VariableDeclaration, {
265
- name: "config",
266
- type: configTypeRef,
267
- omitNone: true
268
- });
265
+ return [_$createComponent(py.SourceFile, {
266
+ path: "types.py",
267
+ get children() {
268
+ return _$createComponent(py.ClassDeclaration, {
269
+ name: "Config",
270
+ refkey: configTypeRef
271
+ });
272
+ }
273
+ }), _$createComponent(py.SourceFile, {
274
+ path: "main.py",
275
+ get children() {
276
+ return _$createComponent(py.VariableDeclaration, {
277
+ name: "config",
278
+ type: configTypeRef,
279
+ omitNone: true
280
+ });
281
+ }
282
+ })];
269
283
  }
270
- })]);
271
- assertFileContents(result, {
284
+ })).toRenderTo({
272
285
  "types.py": `
273
- class Config:
274
- pass
286
+ class Config:
287
+ pass
275
288
 
276
- `,
289
+ `,
277
290
  "main.py": `
278
- from typing import TYPE_CHECKING
291
+ from typing import TYPE_CHECKING
279
292
 
280
- if TYPE_CHECKING:
281
- from types import Config
293
+ if TYPE_CHECKING:
294
+ from types import Config
282
295
 
283
- config: Config
284
- `
296
+ config: Config
297
+ `
285
298
  });
286
299
  });
287
300
  it("handles TypeReference component as type-only import", () => {
288
301
  const myTypeRef = refkey();
289
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
290
- path: "types.py",
291
- get children() {
292
- return _$createComponent(py.ClassDeclaration, {
293
- name: "MyType",
294
- refkey: myTypeRef
295
- });
296
- }
297
- }), _$createComponent(py.SourceFile, {
298
- path: "main.py",
302
+ expect(_$createComponent(TestOutputDirectory, {
299
303
  get children() {
300
- return _$createComponent(py.VariableDeclaration, {
301
- name: "value",
302
- get type() {
303
- return _$createComponent(py.TypeReference, {
304
+ return [_$createComponent(py.SourceFile, {
305
+ path: "types.py",
306
+ get children() {
307
+ return _$createComponent(py.ClassDeclaration, {
308
+ name: "MyType",
304
309
  refkey: myTypeRef
305
310
  });
306
- },
307
- omitNone: true
308
- });
311
+ }
312
+ }), _$createComponent(py.SourceFile, {
313
+ path: "main.py",
314
+ get children() {
315
+ return _$createComponent(py.VariableDeclaration, {
316
+ name: "value",
317
+ get type() {
318
+ return _$createComponent(py.TypeReference, {
319
+ refkey: myTypeRef
320
+ });
321
+ },
322
+ omitNone: true
323
+ });
324
+ }
325
+ })];
309
326
  }
310
- })]);
311
- assertFileContents(result, {
327
+ })).toRenderTo({
312
328
  "types.py": `
313
- class MyType:
314
- pass
329
+ class MyType:
330
+ pass
315
331
 
316
- `,
332
+ `,
317
333
  "main.py": `
318
- from typing import TYPE_CHECKING
334
+ from typing import TYPE_CHECKING
319
335
 
320
- if TYPE_CHECKING:
321
- from types import MyType
336
+ if TYPE_CHECKING:
337
+ from types import MyType
322
338
 
323
- value: MyType
324
- `
339
+ value: MyType
340
+ `
325
341
  });
326
342
  });
327
343
  it("handles class bases as regular import (runtime requirement)", () => {
328
344
  const baseClassRef = refkey();
329
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
330
- path: "base.py",
345
+ expect(_$createComponent(TestOutputDirectory, {
331
346
  get children() {
332
- return _$createComponent(py.ClassDeclaration, {
333
- name: "BaseClass",
334
- refkey: baseClassRef
335
- });
336
- }
337
- }), _$createComponent(py.SourceFile, {
338
- path: "derived.py",
339
- get children() {
340
- return _$createComponent(py.ClassDeclaration, {
341
- name: "DerivedClass",
342
- bases: [baseClassRef]
343
- });
347
+ return [_$createComponent(py.SourceFile, {
348
+ path: "base.py",
349
+ get children() {
350
+ return _$createComponent(py.ClassDeclaration, {
351
+ name: "BaseClass",
352
+ refkey: baseClassRef
353
+ });
354
+ }
355
+ }), _$createComponent(py.SourceFile, {
356
+ path: "derived.py",
357
+ get children() {
358
+ return _$createComponent(py.ClassDeclaration, {
359
+ name: "DerivedClass",
360
+ bases: [baseClassRef]
361
+ });
362
+ }
363
+ })];
344
364
  }
345
- })]);
346
-
347
- // Class bases require runtime access, so they should NOT be
348
- // inside a TYPE_CHECKING block
349
- assertFileContents(result, {
365
+ })).toRenderTo({
350
366
  "base.py": `
351
- class BaseClass:
352
- pass
367
+ class BaseClass:
368
+ pass
353
369
 
354
- `,
370
+ `,
355
371
  "derived.py": `
356
- from base import BaseClass
372
+ from base import BaseClass
357
373
 
358
374
 
359
- class DerivedClass(BaseClass):
360
- pass
375
+ class DerivedClass(BaseClass):
376
+ pass
361
377
 
362
- `
378
+ `
363
379
  });
364
380
  });
365
381
  it("renders regular imports before TYPE_CHECKING block", () => {
366
- // Create a typing module with multiple exports
367
382
  const typingModule = createModule({
368
383
  name: "typing",
369
384
  descriptor: {
370
385
  ".": ["TYPE_CHECKING", "cast"]
371
386
  }
372
387
  });
373
-
374
- // Create a third-party module
375
388
  const requestsModule = createModule({
376
389
  name: "requests",
377
390
  descriptor: {
@@ -379,58 +392,58 @@ describe("TYPE_CHECKING imports", () => {
379
392
  }
380
393
  });
381
394
  const userClassRef = refkey();
382
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
383
- path: "models.py",
384
- get children() {
385
- return _$createComponent(py.ClassDeclaration, {
386
- name: "User",
387
- refkey: userClassRef
388
- });
389
- }
390
- }), _$createComponent(py.SourceFile, {
391
- path: "service.py",
395
+ expect(_$createComponent(TestOutputDirectory, {
396
+ externals: [typingModule, requestsModule],
392
397
  get children() {
393
- return _$createComponent(py.FunctionDeclaration, {
394
- name: "get_users",
395
- parameters: [{
396
- name: "user",
397
- type: userClassRef
398
- }],
399
- returnType: "str",
398
+ return [_$createComponent(py.SourceFile, {
399
+ path: "models.py",
400
+ get children() {
401
+ return _$createComponent(py.ClassDeclaration, {
402
+ name: "User",
403
+ refkey: userClassRef
404
+ });
405
+ }
406
+ }), _$createComponent(py.SourceFile, {
407
+ path: "service.py",
400
408
  get children() {
401
- return _$createComponent(py.StatementList, {
409
+ return _$createComponent(py.FunctionDeclaration, {
410
+ name: "get_users",
411
+ parameters: [{
412
+ name: "user",
413
+ type: userClassRef
414
+ }],
415
+ returnType: "str",
402
416
  get children() {
403
- return [["response = ", _$memo(() => requestsModule["."].get), "(\"https://example.com\")"], ["return ", _$memo(() => typingModule["."].cast), "(str, user)"]];
417
+ return _$createComponent(py.StatementList, {
418
+ get children() {
419
+ return [["response = ", _$memo(() => requestsModule["."].get), "(\"https://example.com\")"], ["return ", _$memo(() => typingModule["."].cast), "(str, user)"]];
420
+ }
421
+ });
404
422
  }
405
423
  });
406
424
  }
407
- });
425
+ })];
408
426
  }
409
- })], {
410
- externals: [typingModule, requestsModule]
411
- });
412
-
413
- // Regular imports first (sorted alphabetically), then TYPE_CHECKING block
414
- assertFileContents(result, {
427
+ })).toRenderTo({
415
428
  "models.py": `
416
- class User:
417
- pass
429
+ class User:
430
+ pass
418
431
 
419
- `,
432
+ `,
420
433
  "service.py": `
421
- from requests import get
422
- from typing import cast
423
- from typing import TYPE_CHECKING
434
+ from requests import get
435
+ from typing import cast
436
+ from typing import TYPE_CHECKING
424
437
 
425
- if TYPE_CHECKING:
426
- from models import User
438
+ if TYPE_CHECKING:
439
+ from models import User
427
440
 
428
441
 
429
- def get_users(user: User) -> str:
430
- response = get("https://example.com")
431
- return cast(str, user)
442
+ def get_users(user: User) -> str:
443
+ response = get("https://example.com")
444
+ return cast(str, user)
432
445
 
433
- `
446
+ `
434
447
  });
435
448
  });
436
449
  });