@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,103 +1,118 @@
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
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
+ fileName: import.meta.url,
20
+ lineNumber: 14,
21
+ columnNumber: 11
22
+ });
23
+ }
16
24
  }, {
17
25
  fileName: import.meta.url,
18
26
  lineNumber: 13,
19
27
  columnNumber: 9
20
- });
21
- }
22
- }, {
23
- fileName: import.meta.url,
24
- lineNumber: 12,
25
- columnNumber: 7
26
- }), _$createComponent(py.SourceFile, {
27
- path: "service.py",
28
- get children() {
29
- return _$createComponent(py.FunctionDeclaration, {
30
- name: "process_user",
31
- parameters: [{
32
- name: "user",
33
- type: userClassRef
34
- }],
35
- returnType: "None",
36
- children: "pass"
28
+ }), _$createComponent(py.SourceFile, {
29
+ path: "service.py",
30
+ get children() {
31
+ return _$createComponent(py.FunctionDeclaration, {
32
+ name: "process_user",
33
+ parameters: [{
34
+ name: "user",
35
+ type: userClassRef
36
+ }],
37
+ returnType: "None",
38
+ children: "pass"
39
+ }, {
40
+ fileName: import.meta.url,
41
+ lineNumber: 17,
42
+ columnNumber: 11
43
+ });
44
+ }
37
45
  }, {
38
46
  fileName: import.meta.url,
39
47
  lineNumber: 16,
40
48
  columnNumber: 9
41
- });
49
+ })];
42
50
  }
43
51
  }, {
44
52
  fileName: import.meta.url,
45
- lineNumber: 15,
53
+ lineNumber: 12,
46
54
  columnNumber: 7
47
- })]);
48
- assertFileContents(result, {
55
+ })).toRenderTo({
49
56
  "models.py": `
50
- class User:
51
- pass
57
+ class User:
58
+ pass
52
59
 
53
- `,
60
+ `,
54
61
  "service.py": `
55
- from typing import TYPE_CHECKING
62
+ from typing import TYPE_CHECKING
56
63
 
57
- if TYPE_CHECKING:
58
- from models import User
64
+ if TYPE_CHECKING:
65
+ from models import User
59
66
 
60
67
 
61
- def process_user(user: User) -> None:
62
- pass
68
+ def process_user(user: User) -> None:
69
+ pass
63
70
 
64
- `
71
+ `
65
72
  });
66
73
  });
67
74
  it("imports value references outside TYPE_CHECKING block", () => {
68
75
  const userClassRef = refkey();
69
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
70
- path: "models.py",
76
+ expect(_$createComponent(TestOutputDirectory, {
71
77
  get children() {
72
- return _$createComponent(py.ClassDeclaration, {
73
- name: "User",
74
- refkey: userClassRef
78
+ return [_$createComponent(py.SourceFile, {
79
+ path: "models.py",
80
+ get children() {
81
+ return _$createComponent(py.ClassDeclaration, {
82
+ name: "User",
83
+ refkey: userClassRef
84
+ }, {
85
+ fileName: import.meta.url,
86
+ lineNumber: 52,
87
+ columnNumber: 11
88
+ });
89
+ }
75
90
  }, {
76
91
  fileName: import.meta.url,
77
92
  lineNumber: 51,
78
93
  columnNumber: 9
79
- });
80
- }
81
- }, {
82
- fileName: import.meta.url,
83
- lineNumber: 50,
84
- columnNumber: 7
85
- }), _$createComponent(py.SourceFile, {
86
- path: "service.py",
87
- get children() {
88
- return _$createComponent(py.FunctionDeclaration, {
89
- name: "create_user",
90
- returnType: "None",
94
+ }), _$createComponent(py.SourceFile, {
95
+ path: "service.py",
91
96
  get children() {
92
- return _$createComponent(py.VariableDeclaration, {
93
- name: "user",
94
- get initializer() {
95
- return _$createComponent(py.ClassInstantiation, {
96
- target: userClassRef
97
+ return _$createComponent(py.FunctionDeclaration, {
98
+ name: "create_user",
99
+ returnType: "None",
100
+ get children() {
101
+ return _$createComponent(py.VariableDeclaration, {
102
+ name: "user",
103
+ get initializer() {
104
+ return _$createComponent(py.ClassInstantiation, {
105
+ target: userClassRef
106
+ }, {
107
+ fileName: import.meta.url,
108
+ lineNumber: 58,
109
+ columnNumber: 28
110
+ });
111
+ }
97
112
  }, {
98
113
  fileName: import.meta.url,
99
- lineNumber: 57,
100
- columnNumber: 26
114
+ lineNumber: 56,
115
+ columnNumber: 13
101
116
  });
102
117
  }
103
118
  }, {
@@ -110,80 +125,87 @@ describe("TYPE_CHECKING imports", () => {
110
125
  fileName: import.meta.url,
111
126
  lineNumber: 54,
112
127
  columnNumber: 9
113
- });
128
+ })];
114
129
  }
115
130
  }, {
116
131
  fileName: import.meta.url,
117
- lineNumber: 53,
132
+ lineNumber: 50,
118
133
  columnNumber: 7
119
- })]);
120
- assertFileContents(result, {
134
+ })).toRenderTo({
121
135
  "models.py": `
122
- class User:
123
- pass
136
+ class User:
137
+ pass
124
138
 
125
- `,
139
+ `,
126
140
  "service.py": `
127
- from models import User
141
+ from models import User
128
142
 
129
143
 
130
- def create_user() -> None:
131
- user = User()
144
+ def create_user() -> None:
145
+ user = User()
132
146
 
133
- `
147
+ `
134
148
  });
135
149
  });
136
150
  it("upgrades type-only import to regular import when also used as value", () => {
137
151
  const userClassRef = refkey();
138
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
139
- path: "models.py",
152
+ expect(_$createComponent(TestOutputDirectory, {
140
153
  get children() {
141
- return _$createComponent(py.ClassDeclaration, {
142
- name: "User",
143
- refkey: userClassRef
154
+ return [_$createComponent(py.SourceFile, {
155
+ path: "models.py",
156
+ get children() {
157
+ return _$createComponent(py.ClassDeclaration, {
158
+ name: "User",
159
+ refkey: userClassRef
160
+ }, {
161
+ fileName: import.meta.url,
162
+ lineNumber: 86,
163
+ columnNumber: 11
164
+ });
165
+ }
144
166
  }, {
145
167
  fileName: import.meta.url,
146
168
  lineNumber: 85,
147
169
  columnNumber: 9
148
- });
149
- }
150
- }, {
151
- fileName: import.meta.url,
152
- lineNumber: 84,
153
- columnNumber: 7
154
- }), _$createComponent(py.SourceFile, {
155
- path: "service.py",
156
- get children() {
157
- return _$createComponent(py.FunctionDeclaration, {
158
- name: "create_user",
159
- parameters: [{
160
- name: "existing",
161
- type: userClassRef
162
- }],
163
- returnType: userClassRef,
170
+ }), _$createComponent(py.SourceFile, {
171
+ path: "service.py",
164
172
  get children() {
165
- return _$createComponent(py.StatementList, {
173
+ return _$createComponent(py.FunctionDeclaration, {
174
+ name: "create_user",
175
+ parameters: [{
176
+ name: "existing",
177
+ type: userClassRef
178
+ }],
179
+ returnType: userClassRef,
166
180
  get children() {
167
- return [_$createComponent(py.VariableDeclaration, {
168
- name: "user",
169
- get initializer() {
170
- return _$createComponent(py.ClassInstantiation, {
171
- target: userClassRef
181
+ return _$createComponent(py.StatementList, {
182
+ get children() {
183
+ return [_$createComponent(py.VariableDeclaration, {
184
+ name: "user",
185
+ get initializer() {
186
+ return _$createComponent(py.ClassInstantiation, {
187
+ target: userClassRef
188
+ }, {
189
+ fileName: import.meta.url,
190
+ lineNumber: 97,
191
+ columnNumber: 30
192
+ });
193
+ }
172
194
  }, {
173
195
  fileName: import.meta.url,
174
- lineNumber: 96,
175
- columnNumber: 28
176
- });
196
+ lineNumber: 95,
197
+ columnNumber: 15
198
+ }), ["return user"]];
177
199
  }
178
200
  }, {
179
201
  fileName: import.meta.url,
180
202
  lineNumber: 94,
181
203
  columnNumber: 13
182
- }), ["return user"]];
204
+ });
183
205
  }
184
206
  }, {
185
207
  fileName: import.meta.url,
186
- lineNumber: 93,
208
+ lineNumber: 89,
187
209
  columnNumber: 11
188
210
  });
189
211
  }
@@ -191,347 +213,370 @@ describe("TYPE_CHECKING imports", () => {
191
213
  fileName: import.meta.url,
192
214
  lineNumber: 88,
193
215
  columnNumber: 9
194
- });
216
+ })];
195
217
  }
196
218
  }, {
197
219
  fileName: import.meta.url,
198
- lineNumber: 87,
220
+ lineNumber: 84,
199
221
  columnNumber: 7
200
- })]);
201
-
202
- // Since User is used both as a type (parameter type, return type) and
203
- // as a value (ClassInstantiation), it should be a regular import
204
- assertFileContents(result, {
222
+ })).toRenderTo({
205
223
  "models.py": `
206
- class User:
207
- pass
224
+ class User:
225
+ pass
208
226
 
209
- `,
227
+ `,
210
228
  "service.py": `
211
- from models import User
229
+ from models import User
212
230
 
213
231
 
214
- def create_user(existing: User) -> User:
215
- user = User()
216
- return user
232
+ def create_user(existing: User) -> User:
233
+ user = User()
234
+ return user
217
235
 
218
- `
236
+ `
219
237
  });
220
238
  });
221
239
  it("handles mixed type-only and regular imports from same module", () => {
222
240
  const userClassRef = refkey();
223
241
  const helperFuncRef = refkey();
224
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
225
- path: "models.py",
242
+ expect(_$createComponent(TestOutputDirectory, {
226
243
  get children() {
227
- return [_$createComponent(py.ClassDeclaration, {
228
- name: "User",
229
- refkey: userClassRef
230
- }, {
231
- fileName: import.meta.url,
232
- lineNumber: 130,
233
- columnNumber: 9
234
- }), _$createComponent(py.FunctionDeclaration, {
235
- name: "helper",
236
- refkey: helperFuncRef,
237
- children: "pass"
244
+ return [_$createComponent(py.SourceFile, {
245
+ path: "models.py",
246
+ get children() {
247
+ return [_$createComponent(py.ClassDeclaration, {
248
+ name: "User",
249
+ refkey: userClassRef
250
+ }, {
251
+ fileName: import.meta.url,
252
+ lineNumber: 129,
253
+ columnNumber: 11
254
+ }), _$createComponent(py.FunctionDeclaration, {
255
+ name: "helper",
256
+ refkey: helperFuncRef,
257
+ children: "pass"
258
+ }, {
259
+ fileName: import.meta.url,
260
+ lineNumber: 130,
261
+ columnNumber: 11
262
+ })];
263
+ }
238
264
  }, {
239
265
  fileName: import.meta.url,
240
- lineNumber: 131,
266
+ lineNumber: 128,
241
267
  columnNumber: 9
242
- })];
243
- }
244
- }, {
245
- fileName: import.meta.url,
246
- lineNumber: 129,
247
- columnNumber: 7
248
- }), _$createComponent(py.SourceFile, {
249
- path: "service.py",
250
- get children() {
251
- return _$createComponent(py.FunctionDeclaration, {
252
- name: "process",
253
- parameters: [{
254
- name: "user",
255
- type: userClassRef
256
- }],
257
- returnType: "None",
268
+ }), _$createComponent(py.SourceFile, {
269
+ path: "service.py",
258
270
  get children() {
259
- return _$createComponent(py.FunctionCallExpression, {
260
- target: helperFuncRef
271
+ return _$createComponent(py.FunctionDeclaration, {
272
+ name: "process",
273
+ parameters: [{
274
+ name: "user",
275
+ type: userClassRef
276
+ }],
277
+ returnType: "None",
278
+ get children() {
279
+ return _$createComponent(py.FunctionCallExpression, {
280
+ target: helperFuncRef
281
+ }, {
282
+ fileName: import.meta.url,
283
+ lineNumber: 140,
284
+ columnNumber: 13
285
+ });
286
+ }
261
287
  }, {
262
288
  fileName: import.meta.url,
263
- lineNumber: 141,
289
+ lineNumber: 135,
264
290
  columnNumber: 11
265
291
  });
266
292
  }
267
293
  }, {
268
294
  fileName: import.meta.url,
269
- lineNumber: 136,
295
+ lineNumber: 134,
270
296
  columnNumber: 9
271
- });
297
+ })];
272
298
  }
273
299
  }, {
274
300
  fileName: import.meta.url,
275
- lineNumber: 135,
301
+ lineNumber: 127,
276
302
  columnNumber: 7
277
- })]);
278
-
279
- // helper is used as a value (function call), User is only used as type
280
- assertFileContents(result, {
303
+ })).toRenderTo({
281
304
  "models.py": `
282
- class User:
283
- pass
305
+ class User:
306
+ pass
284
307
 
285
308
 
286
- def helper():
287
- pass
309
+ def helper():
310
+ pass
288
311
 
289
- `,
312
+ `,
290
313
  "service.py": `
291
- from models import helper
292
- from typing import TYPE_CHECKING
314
+ from models import helper
315
+ from typing import TYPE_CHECKING
293
316
 
294
- if TYPE_CHECKING:
295
- from models import User
317
+ if TYPE_CHECKING:
318
+ from models import User
296
319
 
297
320
 
298
- def process(user: User) -> None:
299
- helper()
321
+ def process(user: User) -> None:
322
+ helper()
300
323
 
301
- `
324
+ `
302
325
  });
303
326
  });
304
327
  it("handles return type as type-only import", () => {
305
328
  const resultTypeRef = refkey();
306
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
307
- path: "types.py",
329
+ expect(_$createComponent(TestOutputDirectory, {
308
330
  get children() {
309
- return _$createComponent(py.ClassDeclaration, {
310
- name: "Result",
311
- refkey: resultTypeRef
331
+ return [_$createComponent(py.SourceFile, {
332
+ path: "types.py",
333
+ get children() {
334
+ return _$createComponent(py.ClassDeclaration, {
335
+ name: "Result",
336
+ refkey: resultTypeRef
337
+ }, {
338
+ fileName: import.meta.url,
339
+ lineNumber: 175,
340
+ columnNumber: 11
341
+ });
342
+ }
312
343
  }, {
313
344
  fileName: import.meta.url,
314
- lineNumber: 177,
345
+ lineNumber: 174,
315
346
  columnNumber: 9
316
- });
317
- }
318
- }, {
319
- fileName: import.meta.url,
320
- lineNumber: 176,
321
- columnNumber: 7
322
- }), _$createComponent(py.SourceFile, {
323
- path: "main.py",
324
- get children() {
325
- return _$createComponent(py.FunctionDeclaration, {
326
- name: "get_result",
327
- returnType: resultTypeRef,
328
- children: "pass"
347
+ }), _$createComponent(py.SourceFile, {
348
+ path: "main.py",
349
+ get children() {
350
+ return _$createComponent(py.FunctionDeclaration, {
351
+ name: "get_result",
352
+ returnType: resultTypeRef,
353
+ children: "pass"
354
+ }, {
355
+ fileName: import.meta.url,
356
+ lineNumber: 178,
357
+ columnNumber: 11
358
+ });
359
+ }
329
360
  }, {
330
361
  fileName: import.meta.url,
331
- lineNumber: 180,
362
+ lineNumber: 177,
332
363
  columnNumber: 9
333
- });
364
+ })];
334
365
  }
335
366
  }, {
336
367
  fileName: import.meta.url,
337
- lineNumber: 179,
368
+ lineNumber: 173,
338
369
  columnNumber: 7
339
- })]);
340
- assertFileContents(result, {
370
+ })).toRenderTo({
341
371
  "types.py": `
342
- class Result:
343
- pass
372
+ class Result:
373
+ pass
344
374
 
345
- `,
375
+ `,
346
376
  "main.py": `
347
- from typing import TYPE_CHECKING
377
+ from typing import TYPE_CHECKING
348
378
 
349
- if TYPE_CHECKING:
350
- from types import Result
379
+ if TYPE_CHECKING:
380
+ from types import Result
351
381
 
352
382
 
353
- def get_result() -> Result:
354
- pass
383
+ def get_result() -> Result:
384
+ pass
355
385
 
356
- `
386
+ `
357
387
  });
358
388
  });
359
389
  it("handles variable type annotation as type-only import", () => {
360
390
  const configTypeRef = refkey();
361
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
362
- path: "types.py",
391
+ expect(_$createComponent(TestOutputDirectory, {
363
392
  get children() {
364
- return _$createComponent(py.ClassDeclaration, {
365
- name: "Config",
366
- refkey: configTypeRef
393
+ return [_$createComponent(py.SourceFile, {
394
+ path: "types.py",
395
+ get children() {
396
+ return _$createComponent(py.ClassDeclaration, {
397
+ name: "Config",
398
+ refkey: configTypeRef
399
+ }, {
400
+ fileName: import.meta.url,
401
+ lineNumber: 209,
402
+ columnNumber: 11
403
+ });
404
+ }
367
405
  }, {
368
406
  fileName: import.meta.url,
369
- lineNumber: 211,
407
+ lineNumber: 208,
370
408
  columnNumber: 9
371
- });
372
- }
373
- }, {
374
- fileName: import.meta.url,
375
- lineNumber: 210,
376
- columnNumber: 7
377
- }), _$createComponent(py.SourceFile, {
378
- path: "main.py",
379
- get children() {
380
- return _$createComponent(py.VariableDeclaration, {
381
- name: "config",
382
- type: configTypeRef,
383
- omitNone: true
409
+ }), _$createComponent(py.SourceFile, {
410
+ path: "main.py",
411
+ get children() {
412
+ return _$createComponent(py.VariableDeclaration, {
413
+ name: "config",
414
+ type: configTypeRef,
415
+ omitNone: true
416
+ }, {
417
+ fileName: import.meta.url,
418
+ lineNumber: 212,
419
+ columnNumber: 11
420
+ });
421
+ }
384
422
  }, {
385
423
  fileName: import.meta.url,
386
- lineNumber: 214,
424
+ lineNumber: 211,
387
425
  columnNumber: 9
388
- });
426
+ })];
389
427
  }
390
428
  }, {
391
429
  fileName: import.meta.url,
392
- lineNumber: 213,
430
+ lineNumber: 207,
393
431
  columnNumber: 7
394
- })]);
395
- assertFileContents(result, {
432
+ })).toRenderTo({
396
433
  "types.py": `
397
- class Config:
398
- pass
434
+ class Config:
435
+ pass
399
436
 
400
- `,
437
+ `,
401
438
  "main.py": `
402
- from typing import TYPE_CHECKING
439
+ from typing import TYPE_CHECKING
403
440
 
404
- if TYPE_CHECKING:
405
- from types import Config
441
+ if TYPE_CHECKING:
442
+ from types import Config
406
443
 
407
- config: Config
408
- `
444
+ config: Config
445
+ `
409
446
  });
410
447
  });
411
448
  it("handles TypeReference component as type-only import", () => {
412
449
  const myTypeRef = refkey();
413
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
414
- path: "types.py",
450
+ expect(_$createComponent(TestOutputDirectory, {
415
451
  get children() {
416
- return _$createComponent(py.ClassDeclaration, {
417
- name: "MyType",
418
- refkey: myTypeRef
452
+ return [_$createComponent(py.SourceFile, {
453
+ path: "types.py",
454
+ get children() {
455
+ return _$createComponent(py.ClassDeclaration, {
456
+ name: "MyType",
457
+ refkey: myTypeRef
458
+ }, {
459
+ fileName: import.meta.url,
460
+ lineNumber: 238,
461
+ columnNumber: 11
462
+ });
463
+ }
419
464
  }, {
420
465
  fileName: import.meta.url,
421
- lineNumber: 240,
466
+ lineNumber: 237,
422
467
  columnNumber: 9
423
- });
424
- }
425
- }, {
426
- fileName: import.meta.url,
427
- lineNumber: 239,
428
- columnNumber: 7
429
- }), _$createComponent(py.SourceFile, {
430
- path: "main.py",
431
- get children() {
432
- return _$createComponent(py.VariableDeclaration, {
433
- name: "value",
434
- get type() {
435
- return _$createComponent(py.TypeReference, {
436
- refkey: myTypeRef
468
+ }), _$createComponent(py.SourceFile, {
469
+ path: "main.py",
470
+ get children() {
471
+ return _$createComponent(py.VariableDeclaration, {
472
+ name: "value",
473
+ get type() {
474
+ return _$createComponent(py.TypeReference, {
475
+ refkey: myTypeRef
476
+ }, {
477
+ fileName: import.meta.url,
478
+ lineNumber: 243,
479
+ columnNumber: 19
480
+ });
481
+ },
482
+ omitNone: true
437
483
  }, {
438
484
  fileName: import.meta.url,
439
- lineNumber: 245,
440
- columnNumber: 17
485
+ lineNumber: 241,
486
+ columnNumber: 11
441
487
  });
442
- },
443
- omitNone: true
488
+ }
444
489
  }, {
445
490
  fileName: import.meta.url,
446
- lineNumber: 243,
491
+ lineNumber: 240,
447
492
  columnNumber: 9
448
- });
493
+ })];
449
494
  }
450
495
  }, {
451
496
  fileName: import.meta.url,
452
- lineNumber: 242,
497
+ lineNumber: 236,
453
498
  columnNumber: 7
454
- })]);
455
- assertFileContents(result, {
499
+ })).toRenderTo({
456
500
  "types.py": `
457
- class MyType:
458
- pass
501
+ class MyType:
502
+ pass
459
503
 
460
- `,
504
+ `,
461
505
  "main.py": `
462
- from typing import TYPE_CHECKING
506
+ from typing import TYPE_CHECKING
463
507
 
464
- if TYPE_CHECKING:
465
- from types import MyType
508
+ if TYPE_CHECKING:
509
+ from types import MyType
466
510
 
467
- value: MyType
468
- `
511
+ value: MyType
512
+ `
469
513
  });
470
514
  });
471
515
  it("handles class bases as regular import (runtime requirement)", () => {
472
516
  const baseClassRef = refkey();
473
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
474
- path: "base.py",
517
+ expect(_$createComponent(TestOutputDirectory, {
475
518
  get children() {
476
- return _$createComponent(py.ClassDeclaration, {
477
- name: "BaseClass",
478
- refkey: baseClassRef
519
+ return [_$createComponent(py.SourceFile, {
520
+ path: "base.py",
521
+ get children() {
522
+ return _$createComponent(py.ClassDeclaration, {
523
+ name: "BaseClass",
524
+ refkey: baseClassRef
525
+ }, {
526
+ fileName: import.meta.url,
527
+ lineNumber: 271,
528
+ columnNumber: 11
529
+ });
530
+ }
479
531
  }, {
480
532
  fileName: import.meta.url,
481
- lineNumber: 273,
533
+ lineNumber: 270,
482
534
  columnNumber: 9
483
- });
484
- }
485
- }, {
486
- fileName: import.meta.url,
487
- lineNumber: 272,
488
- columnNumber: 7
489
- }), _$createComponent(py.SourceFile, {
490
- path: "derived.py",
491
- get children() {
492
- return _$createComponent(py.ClassDeclaration, {
493
- name: "DerivedClass",
494
- bases: [baseClassRef]
535
+ }), _$createComponent(py.SourceFile, {
536
+ path: "derived.py",
537
+ get children() {
538
+ return _$createComponent(py.ClassDeclaration, {
539
+ name: "DerivedClass",
540
+ bases: [baseClassRef]
541
+ }, {
542
+ fileName: import.meta.url,
543
+ lineNumber: 274,
544
+ columnNumber: 11
545
+ });
546
+ }
495
547
  }, {
496
548
  fileName: import.meta.url,
497
- lineNumber: 276,
549
+ lineNumber: 273,
498
550
  columnNumber: 9
499
- });
551
+ })];
500
552
  }
501
553
  }, {
502
554
  fileName: import.meta.url,
503
- lineNumber: 275,
555
+ lineNumber: 269,
504
556
  columnNumber: 7
505
- })]);
506
-
507
- // Class bases require runtime access, so they should NOT be
508
- // inside a TYPE_CHECKING block
509
- assertFileContents(result, {
557
+ })).toRenderTo({
510
558
  "base.py": `
511
- class BaseClass:
512
- pass
559
+ class BaseClass:
560
+ pass
513
561
 
514
- `,
562
+ `,
515
563
  "derived.py": `
516
- from base import BaseClass
564
+ from base import BaseClass
517
565
 
518
566
 
519
- class DerivedClass(BaseClass):
520
- pass
567
+ class DerivedClass(BaseClass):
568
+ pass
521
569
 
522
- `
570
+ `
523
571
  });
524
572
  });
525
573
  it("renders regular imports before TYPE_CHECKING block", () => {
526
- // Create a typing module with multiple exports
527
574
  const typingModule = createModule({
528
575
  name: "typing",
529
576
  descriptor: {
530
577
  ".": ["TYPE_CHECKING", "cast"]
531
578
  }
532
579
  });
533
-
534
- // Create a third-party module
535
580
  const requestsModule = createModule({
536
581
  name: "requests",
537
582
  descriptor: {
@@ -539,78 +584,82 @@ describe("TYPE_CHECKING imports", () => {
539
584
  }
540
585
  });
541
586
  const userClassRef = refkey();
542
- const result = toSourceTextMultiple([_$createComponent(py.SourceFile, {
543
- path: "models.py",
587
+ expect(_$createComponent(TestOutputDirectory, {
588
+ externals: [typingModule, requestsModule],
544
589
  get children() {
545
- return _$createComponent(py.ClassDeclaration, {
546
- name: "User",
547
- refkey: userClassRef
590
+ return [_$createComponent(py.SourceFile, {
591
+ path: "models.py",
592
+ get children() {
593
+ return _$createComponent(py.ClassDeclaration, {
594
+ name: "User",
595
+ refkey: userClassRef
596
+ }, {
597
+ fileName: import.meta.url,
598
+ lineNumber: 314,
599
+ columnNumber: 11
600
+ });
601
+ }
548
602
  }, {
549
603
  fileName: import.meta.url,
550
- lineNumber: 321,
551
- columnNumber: 11
552
- });
553
- }
554
- }, {
555
- fileName: import.meta.url,
556
- lineNumber: 320,
557
- columnNumber: 9
558
- }), _$createComponent(py.SourceFile, {
559
- path: "service.py",
560
- get children() {
561
- return _$createComponent(py.FunctionDeclaration, {
562
- name: "get_users",
563
- parameters: [{
564
- name: "user",
565
- type: userClassRef
566
- }],
567
- returnType: "str",
604
+ lineNumber: 313,
605
+ columnNumber: 9
606
+ }), _$createComponent(py.SourceFile, {
607
+ path: "service.py",
568
608
  get children() {
569
- return _$createComponent(py.StatementList, {
609
+ return _$createComponent(py.FunctionDeclaration, {
610
+ name: "get_users",
611
+ parameters: [{
612
+ name: "user",
613
+ type: userClassRef
614
+ }],
615
+ returnType: "str",
570
616
  get children() {
571
- return [["response = ", _$memo(() => requestsModule["."].get, false, "requestsModule[.].get"), "(\"https://example.com\")"], ["return ", _$memo(() => typingModule["."].cast, false, "typingModule[.].cast"), "(str, user)"]];
617
+ return _$createComponent(py.StatementList, {
618
+ get children() {
619
+ return [["response = ", _$memo(() => requestsModule["."].get, false, "requestsModule[.].get"), "(\"https://example.com\")"], ["return ", _$memo(() => typingModule["."].cast, false, "typingModule[.].cast"), "(str, user)"]];
620
+ }
621
+ }, {
622
+ fileName: import.meta.url,
623
+ lineNumber: 322,
624
+ columnNumber: 13
625
+ });
572
626
  }
573
627
  }, {
574
628
  fileName: import.meta.url,
575
- lineNumber: 329,
576
- columnNumber: 13
629
+ lineNumber: 317,
630
+ columnNumber: 11
577
631
  });
578
632
  }
579
633
  }, {
580
634
  fileName: import.meta.url,
581
- lineNumber: 324,
582
- columnNumber: 11
583
- });
635
+ lineNumber: 316,
636
+ columnNumber: 9
637
+ })];
584
638
  }
585
639
  }, {
586
640
  fileName: import.meta.url,
587
- lineNumber: 323,
588
- columnNumber: 9
589
- })], {
590
- externals: [typingModule, requestsModule]
591
- });
592
-
593
- // Regular imports first (sorted alphabetically), then TYPE_CHECKING block
594
- assertFileContents(result, {
641
+ lineNumber: 312,
642
+ columnNumber: 7
643
+ })).toRenderTo({
595
644
  "models.py": `
596
- class User:
597
- pass
645
+ class User:
646
+ pass
598
647
 
599
- `,
648
+ `,
600
649
  "service.py": `
601
- from requests import get
602
- from typing import cast
603
- from typing import TYPE_CHECKING
650
+ from requests import get
651
+ from typing import cast
652
+ from typing import TYPE_CHECKING
604
653
 
605
- if TYPE_CHECKING:
606
- from models import User
654
+ if TYPE_CHECKING:
655
+ from models import User
607
656
 
608
657
 
609
- def get_users(user: User) -> str:
610
- response = get("https://example.com")
611
- return cast(str, user)
658
+ def get_users(user: User) -> str:
659
+ response = get("https://example.com")
660
+ return cast(str, user)
612
661
 
613
- `
662
+ `
614
663
  });
615
664
  });
616
665
  });