@alloy-js/python 0.4.0-dev.2 → 0.4.0-dev.5

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 (258) hide show
  1. package/dist/dev/src/builtins/python.js +30 -0
  2. package/dist/dev/src/builtins/python.js.map +1 -0
  3. package/dist/dev/src/components/Atom.js +122 -0
  4. package/dist/dev/src/components/Atom.js.map +1 -0
  5. package/dist/dev/src/components/CallSignature.js +195 -0
  6. package/dist/dev/src/components/CallSignature.js.map +1 -0
  7. package/dist/dev/src/components/ClassDeclaration.js +112 -0
  8. package/dist/dev/src/components/ClassDeclaration.js.map +1 -0
  9. package/dist/dev/src/components/ClassInstantiation.js +40 -0
  10. package/dist/dev/src/components/ClassInstantiation.js.map +1 -0
  11. package/dist/dev/src/components/ClassMethodDeclaration.js +40 -0
  12. package/dist/dev/src/components/ClassMethodDeclaration.js.map +1 -0
  13. package/dist/dev/src/components/ConstructorDeclaration.js +39 -0
  14. package/dist/dev/src/components/ConstructorDeclaration.js.map +1 -0
  15. package/dist/dev/src/components/DataclassDeclaration.js +177 -0
  16. package/dist/dev/src/components/DataclassDeclaration.js.map +1 -0
  17. package/dist/dev/src/components/Declaration.js +31 -0
  18. package/dist/dev/src/components/Declaration.js.map +1 -0
  19. package/dist/dev/src/components/DunderMethodDeclaration.js +33 -0
  20. package/dist/dev/src/components/DunderMethodDeclaration.js.map +1 -0
  21. package/dist/dev/src/components/EnumDeclaration.js +259 -0
  22. package/dist/dev/src/components/EnumDeclaration.js.map +1 -0
  23. package/dist/dev/src/components/EnumMember.js +95 -0
  24. package/dist/dev/src/components/EnumMember.js.map +1 -0
  25. package/dist/dev/src/components/FunctionBase.js +130 -0
  26. package/dist/dev/src/components/FunctionBase.js.map +1 -0
  27. package/dist/dev/src/components/FunctionCallExpression.js +53 -0
  28. package/dist/dev/src/components/FunctionCallExpression.js.map +1 -0
  29. package/dist/dev/src/components/FunctionDeclaration.js +45 -0
  30. package/dist/dev/src/components/FunctionDeclaration.js.map +1 -0
  31. package/dist/dev/src/components/FutureStatement.js +31 -0
  32. package/dist/dev/src/components/FutureStatement.js.map +1 -0
  33. package/dist/dev/src/components/ImportStatement.js +167 -0
  34. package/dist/dev/src/components/ImportStatement.js.map +1 -0
  35. package/dist/dev/src/components/LexicalScope.js +26 -0
  36. package/dist/dev/src/components/LexicalScope.js.map +1 -0
  37. package/dist/dev/src/components/MemberExpression.js +290 -0
  38. package/dist/dev/src/components/MemberExpression.js.map +1 -0
  39. package/dist/dev/src/components/MemberScope.js +23 -0
  40. package/dist/dev/src/components/MemberScope.js.map +1 -0
  41. package/dist/dev/src/components/MethodBase.js +40 -0
  42. package/dist/dev/src/components/MethodBase.js.map +1 -0
  43. package/dist/dev/src/components/MethodDeclaration.js +38 -0
  44. package/dist/dev/src/components/MethodDeclaration.js.map +1 -0
  45. package/dist/dev/src/components/PropertyDeclaration.js +287 -0
  46. package/dist/dev/src/components/PropertyDeclaration.js.map +1 -0
  47. package/dist/dev/src/components/PyDoc.js +1478 -0
  48. package/dist/dev/src/components/PyDoc.js.map +1 -0
  49. package/dist/dev/src/components/PythonBlock.js +35 -0
  50. package/dist/dev/src/components/PythonBlock.js.map +1 -0
  51. package/dist/dev/src/components/Reference.js +23 -0
  52. package/dist/dev/src/components/Reference.js.map +1 -0
  53. package/dist/dev/src/components/SourceFile.js +385 -0
  54. package/dist/dev/src/components/SourceFile.js.map +1 -0
  55. package/dist/dev/src/components/StatementList.js +34 -0
  56. package/dist/dev/src/components/StatementList.js.map +1 -0
  57. package/dist/dev/src/components/StaticMethodDeclaration.js +40 -0
  58. package/dist/dev/src/components/StaticMethodDeclaration.js.map +1 -0
  59. package/dist/dev/src/components/TypeArguments.js +22 -0
  60. package/dist/dev/src/components/TypeArguments.js.map +1 -0
  61. package/dist/dev/src/components/TypeRefContext.js +33 -0
  62. package/dist/dev/src/components/TypeRefContext.js.map +1 -0
  63. package/dist/dev/src/components/TypeReference.js +67 -0
  64. package/dist/dev/src/components/TypeReference.js.map +1 -0
  65. package/dist/dev/src/components/UnionTypeExpression.js +57 -0
  66. package/dist/dev/src/components/UnionTypeExpression.js.map +1 -0
  67. package/dist/dev/src/components/VariableDeclaration.js +150 -0
  68. package/dist/dev/src/components/VariableDeclaration.js.map +1 -0
  69. package/dist/dev/src/components/index.js +32 -0
  70. package/dist/dev/src/components/index.js.map +1 -0
  71. package/dist/dev/src/context/index.js +2 -0
  72. package/dist/dev/src/context/index.js.map +1 -0
  73. package/dist/dev/src/context/type-ref-context.js +17 -0
  74. package/dist/dev/src/context/type-ref-context.js.map +1 -0
  75. package/dist/dev/src/create-module.js +64 -0
  76. package/dist/dev/src/create-module.js.map +1 -0
  77. package/dist/dev/src/index.js +8 -0
  78. package/dist/dev/src/index.js.map +1 -0
  79. package/dist/dev/src/name-conflict-resolver.js +8 -0
  80. package/dist/dev/src/name-conflict-resolver.js.map +1 -0
  81. package/dist/dev/src/name-policy.js +48 -0
  82. package/dist/dev/src/name-policy.js.map +1 -0
  83. package/dist/dev/src/parameter-descriptor.js +8 -0
  84. package/dist/dev/src/parameter-descriptor.js.map +1 -0
  85. package/dist/dev/src/symbol-creation.js +58 -0
  86. package/dist/dev/src/symbol-creation.js.map +1 -0
  87. package/dist/dev/src/symbols/factories.js +28 -0
  88. package/dist/dev/src/symbols/factories.js.map +1 -0
  89. package/dist/dev/src/symbols/index.js +8 -0
  90. package/dist/dev/src/symbols/index.js.map +1 -0
  91. package/dist/dev/src/symbols/python-lexical-scope.js +15 -0
  92. package/dist/dev/src/symbols/python-lexical-scope.js.map +1 -0
  93. package/dist/dev/src/symbols/python-member-scope.js +7 -0
  94. package/dist/dev/src/symbols/python-member-scope.js.map +1 -0
  95. package/dist/dev/src/symbols/python-module-scope.js +86 -0
  96. package/dist/dev/src/symbols/python-module-scope.js.map +1 -0
  97. package/dist/dev/src/symbols/python-output-symbol.js +73 -0
  98. package/dist/dev/src/symbols/python-output-symbol.js.map +1 -0
  99. package/dist/dev/src/symbols/reference.js +87 -0
  100. package/dist/dev/src/symbols/reference.js.map +1 -0
  101. package/dist/dev/src/symbols/scopes.js +13 -0
  102. package/dist/dev/src/symbols/scopes.js.map +1 -0
  103. package/dist/dev/src/utils.js +13 -0
  104. package/dist/dev/src/utils.js.map +1 -0
  105. package/dist/dev/test/callsignatures.test.js +482 -0
  106. package/dist/dev/test/callsignatures.test.js.map +1 -0
  107. package/dist/dev/test/class-method-declaration.test.js +85 -0
  108. package/dist/dev/test/class-method-declaration.test.js.map +1 -0
  109. package/dist/dev/test/classdeclarations.test.js +654 -0
  110. package/dist/dev/test/classdeclarations.test.js.map +1 -0
  111. package/dist/dev/test/classinstantiations.test.js +281 -0
  112. package/dist/dev/test/classinstantiations.test.js.map +1 -0
  113. package/dist/dev/test/constructordeclaration.test.js +86 -0
  114. package/dist/dev/test/constructordeclaration.test.js.map +1 -0
  115. package/dist/dev/test/dataclassdeclarations.test.js +1068 -0
  116. package/dist/dev/test/dataclassdeclarations.test.js.map +1 -0
  117. package/dist/dev/test/dundermethoddeclaration.test.js +93 -0
  118. package/dist/dev/test/dundermethoddeclaration.test.js.map +1 -0
  119. package/dist/dev/test/enums.test.js +263 -0
  120. package/dist/dev/test/enums.test.js.map +1 -0
  121. package/dist/dev/test/externals.test.js +307 -0
  122. package/dist/dev/test/externals.test.js.map +1 -0
  123. package/dist/dev/test/factories.test.js +122 -0
  124. package/dist/dev/test/factories.test.js.map +1 -0
  125. package/dist/dev/test/functioncallexpressions.test.js +257 -0
  126. package/dist/dev/test/functioncallexpressions.test.js.map +1 -0
  127. package/dist/dev/test/functiondeclaration.test.js +817 -0
  128. package/dist/dev/test/functiondeclaration.test.js.map +1 -0
  129. package/dist/dev/test/imports.test.js +372 -0
  130. package/dist/dev/test/imports.test.js.map +1 -0
  131. package/dist/dev/test/memberexpressions.test.js +1668 -0
  132. package/dist/dev/test/memberexpressions.test.js.map +1 -0
  133. package/dist/dev/test/methoddeclaration.test.js +344 -0
  134. package/dist/dev/test/methoddeclaration.test.js.map +1 -0
  135. package/dist/dev/test/namepolicies.test.js +154 -0
  136. package/dist/dev/test/namepolicies.test.js.map +1 -0
  137. package/dist/dev/test/propertydeclaration.test.js +354 -0
  138. package/dist/dev/test/propertydeclaration.test.js.map +1 -0
  139. package/dist/dev/test/pydocs.test.js +1675 -0
  140. package/dist/dev/test/pydocs.test.js.map +1 -0
  141. package/dist/dev/test/references.test.js +66 -0
  142. package/dist/dev/test/references.test.js.map +1 -0
  143. package/dist/dev/test/sourcefiles.test.js +1802 -0
  144. package/dist/dev/test/sourcefiles.test.js.map +1 -0
  145. package/dist/dev/test/staticmethoddeclaration.test.js +85 -0
  146. package/dist/dev/test/staticmethoddeclaration.test.js.map +1 -0
  147. package/dist/dev/test/type-checking-imports.test.js +617 -0
  148. package/dist/dev/test/type-checking-imports.test.js.map +1 -0
  149. package/dist/dev/test/typereference.test.js +79 -0
  150. package/dist/dev/test/typereference.test.js.map +1 -0
  151. package/dist/dev/test/uniontypeexpression.test.js +307 -0
  152. package/dist/dev/test/uniontypeexpression.test.js.map +1 -0
  153. package/dist/dev/test/utils.js +100 -0
  154. package/dist/dev/test/utils.js.map +1 -0
  155. package/dist/dev/test/values.test.js +182 -0
  156. package/dist/dev/test/values.test.js.map +1 -0
  157. package/dist/dev/test/variables.test.js +363 -0
  158. package/dist/dev/test/variables.test.js.map +1 -0
  159. package/dist/src/components/CallSignature.d.ts.map +1 -1
  160. package/dist/src/components/CallSignature.js +12 -3
  161. package/dist/src/components/CallSignature.js.map +1 -1
  162. package/dist/src/components/ImportStatement.d.ts +12 -0
  163. package/dist/src/components/ImportStatement.d.ts.map +1 -1
  164. package/dist/src/components/ImportStatement.js +47 -5
  165. package/dist/src/components/ImportStatement.js.map +1 -1
  166. package/dist/src/components/MemberExpression.d.ts +1 -1
  167. package/dist/src/components/MemberExpression.d.ts.map +1 -1
  168. package/dist/src/components/MemberExpression.js +98 -180
  169. package/dist/src/components/MemberExpression.js.map +1 -1
  170. package/dist/src/components/Reference.d.ts.map +1 -1
  171. package/dist/src/components/Reference.js +5 -1
  172. package/dist/src/components/Reference.js.map +1 -1
  173. package/dist/src/components/SourceFile.d.ts +1 -1
  174. package/dist/src/components/SourceFile.d.ts.map +1 -1
  175. package/dist/src/components/SourceFile.js +46 -7
  176. package/dist/src/components/SourceFile.js.map +1 -1
  177. package/dist/src/components/TypeRefContext.d.ts +26 -0
  178. package/dist/src/components/TypeRefContext.d.ts.map +1 -0
  179. package/dist/src/components/TypeRefContext.js +29 -0
  180. package/dist/src/components/TypeRefContext.js.map +1 -0
  181. package/dist/src/components/TypeReference.d.ts +5 -0
  182. package/dist/src/components/TypeReference.d.ts.map +1 -1
  183. package/dist/src/components/TypeReference.js +19 -9
  184. package/dist/src/components/TypeReference.js.map +1 -1
  185. package/dist/src/components/VariableDeclaration.d.ts.map +1 -1
  186. package/dist/src/components/VariableDeclaration.js +7 -2
  187. package/dist/src/components/VariableDeclaration.js.map +1 -1
  188. package/dist/src/components/index.d.ts +1 -1
  189. package/dist/src/components/index.d.ts.map +1 -1
  190. package/dist/src/components/index.js +1 -1
  191. package/dist/src/components/index.js.map +1 -1
  192. package/dist/src/context/index.d.ts +2 -0
  193. package/dist/src/context/index.d.ts.map +1 -0
  194. package/dist/src/context/index.js +2 -0
  195. package/dist/src/context/index.js.map +1 -0
  196. package/dist/src/context/type-ref-context.d.ts +13 -0
  197. package/dist/src/context/type-ref-context.d.ts.map +1 -0
  198. package/dist/src/context/type-ref-context.js +17 -0
  199. package/dist/src/context/type-ref-context.js.map +1 -0
  200. package/dist/src/symbols/python-module-scope.d.ts +13 -1
  201. package/dist/src/symbols/python-module-scope.d.ts.map +1 -1
  202. package/dist/src/symbols/python-module-scope.js +36 -2
  203. package/dist/src/symbols/python-module-scope.js.map +1 -1
  204. package/dist/src/symbols/python-output-symbol.d.ts +11 -0
  205. package/dist/src/symbols/python-output-symbol.d.ts.map +1 -1
  206. package/dist/src/symbols/python-output-symbol.js +26 -2
  207. package/dist/src/symbols/python-output-symbol.js.map +1 -1
  208. package/dist/src/symbols/reference.d.ts +8 -1
  209. package/dist/src/symbols/reference.d.ts.map +1 -1
  210. package/dist/src/symbols/reference.js +4 -2
  211. package/dist/src/symbols/reference.js.map +1 -1
  212. package/dist/test/dataclassdeclarations.test.js +5 -2
  213. package/dist/test/dataclassdeclarations.test.js.map +1 -1
  214. package/dist/test/externals.test.js +8 -2
  215. package/dist/test/externals.test.js.map +1 -1
  216. package/dist/test/functiondeclaration.test.js +6 -3
  217. package/dist/test/functiondeclaration.test.js.map +1 -1
  218. package/dist/test/imports.test.js +3 -3
  219. package/dist/test/imports.test.js.map +1 -1
  220. package/dist/test/references.test.js +1 -1
  221. package/dist/test/references.test.js.map +1 -1
  222. package/dist/test/sourcefiles.test.js +26 -26
  223. package/dist/test/sourcefiles.test.js.map +1 -1
  224. package/dist/test/type-checking-imports.test.d.ts +2 -0
  225. package/dist/test/type-checking-imports.test.d.ts.map +1 -0
  226. package/dist/test/type-checking-imports.test.js +437 -0
  227. package/dist/test/type-checking-imports.test.js.map +1 -0
  228. package/dist/test/uniontypeexpression.test.js +4 -1
  229. package/dist/test/uniontypeexpression.test.js.map +1 -1
  230. package/dist/test/variables.test.js +4 -1
  231. package/dist/test/variables.test.js.map +1 -1
  232. package/dist/tsconfig.tsbuildinfo +1 -1
  233. package/package.json +6 -4
  234. package/src/components/CallSignature.tsx +6 -2
  235. package/src/components/ImportStatement.tsx +52 -5
  236. package/src/components/MemberExpression.tsx +174 -298
  237. package/src/components/Reference.tsx +3 -1
  238. package/src/components/SourceFile.tsx +44 -8
  239. package/src/components/TypeRefContext.tsx +36 -0
  240. package/src/components/TypeReference.tsx +15 -7
  241. package/src/components/VariableDeclaration.tsx +5 -1
  242. package/src/components/index.ts +1 -1
  243. package/src/context/index.ts +1 -0
  244. package/src/context/type-ref-context.tsx +16 -0
  245. package/src/symbols/python-module-scope.ts +55 -2
  246. package/src/symbols/python-output-symbol.ts +32 -1
  247. package/src/symbols/reference.tsx +10 -0
  248. package/temp/api.json +443 -338
  249. package/test/dataclassdeclarations.test.tsx +8 -2
  250. package/test/externals.test.tsx +8 -2
  251. package/test/functiondeclaration.test.tsx +6 -3
  252. package/test/imports.test.tsx +6 -6
  253. package/test/references.test.tsx +1 -1
  254. package/test/sourcefiles.test.tsx +13 -13
  255. package/test/type-checking-imports.test.tsx +363 -0
  256. package/test/uniontypeexpression.test.tsx +4 -1
  257. package/test/variables.test.tsx +4 -1
  258. package/vitest.config.ts +8 -0
@@ -73,7 +73,10 @@ describe("DataclassDeclaration", () => {
73
73
  expect(res).toRenderTo(
74
74
  d`
75
75
  from dataclasses import dataclass
76
- from dataclasses import KW_ONLY
76
+ from typing import TYPE_CHECKING
77
+
78
+ if TYPE_CHECKING:
79
+ from dataclasses import KW_ONLY
77
80
 
78
81
 
79
82
  @dataclass
@@ -624,7 +627,10 @@ describe("DataclassDeclaration", () => {
624
627
  name="user"
625
628
  type={userRefkey}
626
629
  initializer={
627
- <py.ClassInstantiation target="User" args={["1", '"Alice"']} />
630
+ <py.ClassInstantiation
631
+ target={userRefkey}
632
+ args={["1", '"Alice"']}
633
+ />
628
634
  }
629
635
  />
630
636
  <hbr />
@@ -92,7 +92,10 @@ it("uses import from external library in multiple functions", () => {
92
92
  const expected = d`
93
93
  from requests import get
94
94
  from requests import post
95
- from requests.models import Response
95
+ from typing import TYPE_CHECKING
96
+
97
+ if TYPE_CHECKING:
98
+ from requests.models import Response
96
99
 
97
100
 
98
101
  def get_user(user_id: int) -> Response:
@@ -169,7 +172,10 @@ it("uses import from external library in multiple class methods", () => {
169
172
  const expected = d`
170
173
  from requests import get
171
174
  from requests import post
172
- from requests.models import Response
175
+ from typing import TYPE_CHECKING
176
+
177
+ if TYPE_CHECKING:
178
+ from requests.models import Response
173
179
 
174
180
 
175
181
  class UserClient:
@@ -450,9 +450,12 @@ describe("Function Declaration", () => {
450
450
 
451
451
  `,
452
452
  "usage.py": `
453
- from mod1 import Foo
454
- from mod2 import A
455
- from mod2 import B
453
+ from typing import TYPE_CHECKING
454
+
455
+ if TYPE_CHECKING:
456
+ from mod1 import Foo
457
+ from mod2 import A
458
+ from mod2 import B
456
459
 
457
460
 
458
461
  async def foo(x: A, y: B, *args, **kwargs) -> Foo:
@@ -1,6 +1,9 @@
1
1
  import { refkey } from "@alloy-js/core";
2
2
  import { describe, expect, it } from "vitest";
3
- import { ImportStatement } from "../src/components/ImportStatement.jsx";
3
+ import {
4
+ ImportStatement,
5
+ ImportStatements,
6
+ } from "../src/components/ImportStatement.jsx";
4
7
  import * as py from "../src/index.js";
5
8
  import { createPythonSymbol } from "../src/symbol-creation.js";
6
9
  import { ImportedSymbol, ImportRecords } from "../src/symbols/index.js";
@@ -56,7 +59,7 @@ describe("ImportStatements", () => {
56
59
  [sysModuleScope, { symbols: new Set<ImportedSymbol>() }],
57
60
  ]);
58
61
 
59
- const result = toSourceText([<py.ImportStatements records={records} />]);
62
+ const result = toSourceText([<ImportStatements records={records} />]);
60
63
  const expected = `
61
64
  from math import pi
62
65
  from math import sqrt
@@ -85,10 +88,7 @@ describe("ImportStatements", () => {
85
88
  ]);
86
89
 
87
90
  const result = toSourceText([
88
- <py.ImportStatements
89
- records={records}
90
- joinImportsFromSameModule={true}
91
- />,
91
+ <ImportStatements records={records} joinImportsFromSameModule={true} />,
92
92
  ]);
93
93
  const expected = `
94
94
  from math import pi, sqrt
@@ -15,7 +15,7 @@ describe("Reference", () => {
15
15
  name="current_user"
16
16
  type={rk1}
17
17
  initializer={
18
- <py.ClassInstantiation target="User" args={['"Marvin"']} />
18
+ <py.ClassInstantiation target={rk1} args={['"Marvin"']} />
19
19
  }
20
20
  />
21
21
  </py.SourceFile>,
@@ -312,7 +312,7 @@ it("only futureImports before definition", () => {
312
312
  const content = (
313
313
  <py.SourceFile
314
314
  path="test.py"
315
- futureImports={<py.FutureStatement feature="annotations" />}
315
+ futureImports={[<py.FutureStatement feature="annotations" />]}
316
316
  >
317
317
  <py.FunctionDeclaration name="hello">pass</py.FunctionDeclaration>
318
318
  </py.SourceFile>
@@ -333,7 +333,7 @@ it("only futureImports before non-definition", () => {
333
333
  const content = (
334
334
  <py.SourceFile
335
335
  path="test.py"
336
- futureImports={<py.FutureStatement feature="annotations" />}
336
+ futureImports={[<py.FutureStatement feature="annotations" />]}
337
337
  >
338
338
  <py.VariableDeclaration name="x" initializer={42} />
339
339
  </py.SourceFile>
@@ -393,7 +393,7 @@ it("doc + futureImports before definition", () => {
393
393
  <py.SourceFile
394
394
  path="test.py"
395
395
  doc={moduleDoc}
396
- futureImports={<py.FutureStatement feature="annotations" />}
396
+ futureImports={[<py.FutureStatement feature="annotations" />]}
397
397
  >
398
398
  <py.FunctionDeclaration name="hello">pass</py.FunctionDeclaration>
399
399
  </py.SourceFile>
@@ -423,7 +423,7 @@ it("doc + futureImports before non-definition", () => {
423
423
  <py.SourceFile
424
424
  path="test.py"
425
425
  doc={moduleDoc}
426
- futureImports={<py.FutureStatement feature="annotations" />}
426
+ futureImports={[<py.FutureStatement feature="annotations" />]}
427
427
  >
428
428
  <py.VariableDeclaration name="x" initializer={42} />
429
429
  </py.SourceFile>
@@ -498,7 +498,7 @@ it("futureImports + imports before definition", () => {
498
498
  const content = (
499
499
  <py.SourceFile
500
500
  path="test.py"
501
- futureImports={<py.FutureStatement feature="annotations" />}
501
+ futureImports={[<py.FutureStatement feature="annotations" />]}
502
502
  >
503
503
  <py.DataclassDeclaration name="User">
504
504
  <py.VariableDeclaration name="name" type="str" />
@@ -525,7 +525,7 @@ it("futureImports + imports before non-definition", () => {
525
525
  const content = (
526
526
  <py.SourceFile
527
527
  path="test.py"
528
- futureImports={<py.FutureStatement feature="annotations" />}
528
+ futureImports={[<py.FutureStatement feature="annotations" />]}
529
529
  >
530
530
  <py.VariableDeclaration
531
531
  name="x"
@@ -552,7 +552,7 @@ it("doc + futureImports + imports before definition", () => {
552
552
  <py.SourceFile
553
553
  path="test.py"
554
554
  doc={moduleDoc}
555
- futureImports={<py.FutureStatement feature="annotations" />}
555
+ futureImports={[<py.FutureStatement feature="annotations" />]}
556
556
  >
557
557
  <py.DataclassDeclaration name="User">
558
558
  <py.VariableDeclaration name="name" type="str" />
@@ -588,7 +588,7 @@ it("doc + futureImports + imports before non-definition", () => {
588
588
  <py.SourceFile
589
589
  path="test.py"
590
590
  doc={moduleDoc}
591
- futureImports={<py.FutureStatement feature="annotations" />}
591
+ futureImports={[<py.FutureStatement feature="annotations" />]}
592
592
  >
593
593
  <py.VariableDeclaration
594
594
  name="x"
@@ -642,7 +642,7 @@ it("only futureImports in file (no children)", () => {
642
642
  const content = (
643
643
  <py.SourceFile
644
644
  path="test.py"
645
- futureImports={<py.FutureStatement feature="annotations" />}
645
+ futureImports={[<py.FutureStatement feature="annotations" />]}
646
646
  />
647
647
  );
648
648
 
@@ -661,7 +661,7 @@ it("doc + futureImports in file (no children)", () => {
661
661
  <py.SourceFile
662
662
  path="test.py"
663
663
  doc={moduleDoc}
664
- futureImports={<py.FutureStatement feature="annotations" />}
664
+ futureImports={[<py.FutureStatement feature="annotations" />]}
665
665
  />
666
666
  );
667
667
 
@@ -743,7 +743,7 @@ it("headerComment + futureImports before definition", () => {
743
743
  <py.SourceFile
744
744
  path="test.py"
745
745
  headerComment="Copyright 2024 My Company"
746
- futureImports={<py.FutureStatement feature="annotations" />}
746
+ futureImports={[<py.FutureStatement feature="annotations" />]}
747
747
  >
748
748
  <py.FunctionDeclaration name="hello">pass</py.FunctionDeclaration>
749
749
  </py.SourceFile>
@@ -797,7 +797,7 @@ it("headerComment + doc + futureImports before definition", () => {
797
797
  path="test.py"
798
798
  headerComment="Copyright 2024 My Company"
799
799
  doc={moduleDoc}
800
- futureImports={<py.FutureStatement feature="annotations" />}
800
+ futureImports={[<py.FutureStatement feature="annotations" />]}
801
801
  >
802
802
  <py.FunctionDeclaration name="hello">pass</py.FunctionDeclaration>
803
803
  </py.SourceFile>
@@ -829,7 +829,7 @@ it("headerComment + doc + futureImports + imports before definition", () => {
829
829
  path="test.py"
830
830
  headerComment="Copyright 2024 My Company"
831
831
  doc={moduleDoc}
832
- futureImports={<py.FutureStatement feature="annotations" />}
832
+ futureImports={[<py.FutureStatement feature="annotations" />]}
833
833
  >
834
834
  <py.DataclassDeclaration name="User">
835
835
  <py.VariableDeclaration name="name" type="str" />
@@ -0,0 +1,363 @@
1
+ import { refkey } from "@alloy-js/core";
2
+ import { describe, it } from "vitest";
3
+ import { createModule } from "../src/create-module.js";
4
+ import * as py from "../src/index.js";
5
+ import { assertFileContents, toSourceTextMultiple } from "./utils.jsx";
6
+
7
+ describe("TYPE_CHECKING imports", () => {
8
+ it("imports type-only references inside TYPE_CHECKING block", () => {
9
+ const userClassRef = refkey();
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:
29
+ pass
30
+
31
+ `,
32
+ "service.py": `
33
+ from typing import TYPE_CHECKING
34
+
35
+ if TYPE_CHECKING:
36
+ from models import User
37
+
38
+
39
+ def process_user(user: User) -> None:
40
+ pass
41
+
42
+ `,
43
+ });
44
+ });
45
+
46
+ it("imports value references outside TYPE_CHECKING block", () => {
47
+ const userClassRef = refkey();
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, {
64
+ "models.py": `
65
+ class User:
66
+ pass
67
+
68
+ `,
69
+ "service.py": `
70
+ from models import User
71
+
72
+
73
+ def create_user() -> None:
74
+ user = User()
75
+
76
+ `,
77
+ });
78
+ });
79
+
80
+ it("upgrades type-only import to regular import when also used as value", () => {
81
+ const userClassRef = refkey();
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, {
107
+ "models.py": `
108
+ class User:
109
+ pass
110
+
111
+ `,
112
+ "service.py": `
113
+ from models import User
114
+
115
+
116
+ def create_user(existing: User) -> User:
117
+ user = User()
118
+ return user
119
+
120
+ `,
121
+ });
122
+ });
123
+
124
+ it("handles mixed type-only and regular imports from same module", () => {
125
+ const userClassRef = refkey();
126
+ const helperFuncRef = refkey();
127
+
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:
150
+ pass
151
+
152
+
153
+ def helper():
154
+ pass
155
+
156
+ `,
157
+ "service.py": `
158
+ from models import helper
159
+ from typing import TYPE_CHECKING
160
+
161
+ if TYPE_CHECKING:
162
+ from models import User
163
+
164
+
165
+ def process(user: User) -> None:
166
+ helper()
167
+
168
+ `,
169
+ });
170
+ });
171
+
172
+ it("handles return type as type-only import", () => {
173
+ const resultTypeRef = refkey();
174
+
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:
189
+ pass
190
+
191
+ `,
192
+ "main.py": `
193
+ from typing import TYPE_CHECKING
194
+
195
+ if TYPE_CHECKING:
196
+ from types import Result
197
+
198
+
199
+ def get_result() -> Result:
200
+ pass
201
+
202
+ `,
203
+ });
204
+ });
205
+
206
+ it("handles variable type annotation as type-only import", () => {
207
+ const configTypeRef = refkey();
208
+
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, {
219
+ "types.py": `
220
+ class Config:
221
+ pass
222
+
223
+ `,
224
+ "main.py": `
225
+ from typing import TYPE_CHECKING
226
+
227
+ if TYPE_CHECKING:
228
+ from types import Config
229
+
230
+ config: Config
231
+ `,
232
+ });
233
+ });
234
+
235
+ it("handles TypeReference component as type-only import", () => {
236
+ const myTypeRef = refkey();
237
+
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, {
252
+ "types.py": `
253
+ class MyType:
254
+ pass
255
+
256
+ `,
257
+ "main.py": `
258
+ from typing import TYPE_CHECKING
259
+
260
+ if TYPE_CHECKING:
261
+ from types import MyType
262
+
263
+ value: MyType
264
+ `,
265
+ });
266
+ });
267
+
268
+ it("handles class bases as regular import (runtime requirement)", () => {
269
+ const baseClassRef = refkey();
270
+
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, {
283
+ "base.py": `
284
+ class BaseClass:
285
+ pass
286
+
287
+ `,
288
+ "derived.py": `
289
+ from base import BaseClass
290
+
291
+
292
+ class DerivedClass(BaseClass):
293
+ pass
294
+
295
+ `,
296
+ });
297
+ });
298
+
299
+ it("renders regular imports before TYPE_CHECKING block", () => {
300
+ // Create a typing module with multiple exports
301
+ const typingModule = createModule({
302
+ name: "typing",
303
+ descriptor: {
304
+ ".": ["TYPE_CHECKING", "cast"],
305
+ },
306
+ });
307
+
308
+ // Create a third-party module
309
+ const requestsModule = createModule({
310
+ name: "requests",
311
+ descriptor: {
312
+ ".": ["get"],
313
+ },
314
+ });
315
+
316
+ const userClassRef = refkey();
317
+
318
+ const result = toSourceTextMultiple(
319
+ [
320
+ <py.SourceFile path="models.py">
321
+ <py.ClassDeclaration name="User" refkey={userClassRef} />
322
+ </py.SourceFile>,
323
+ <py.SourceFile path="service.py">
324
+ <py.FunctionDeclaration
325
+ name="get_users"
326
+ parameters={[{ name: "user", type: userClassRef }]}
327
+ returnType="str"
328
+ >
329
+ <py.StatementList>
330
+ {/* Use cast as a value (function call) to make it a regular import */}
331
+ <>response = {requestsModule["."].get}("https://example.com")</>
332
+ <>return {typingModule["."].cast}(str, user)</>
333
+ </py.StatementList>
334
+ </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, {
342
+ "models.py": `
343
+ class User:
344
+ pass
345
+
346
+ `,
347
+ "service.py": `
348
+ from requests import get
349
+ from typing import cast
350
+ from typing import TYPE_CHECKING
351
+
352
+ if TYPE_CHECKING:
353
+ from models import User
354
+
355
+
356
+ def get_users(user: User) -> str:
357
+ response = get("https://example.com")
358
+ return cast(str, user)
359
+
360
+ `,
361
+ });
362
+ });
363
+ });
@@ -139,7 +139,10 @@ describe("UnionTypeExpression", () => {
139
139
 
140
140
  `,
141
141
  "use.py": `
142
- from defs import Bar
142
+ from typing import TYPE_CHECKING
143
+
144
+ if TYPE_CHECKING:
145
+ from defs import Bar
143
146
 
144
147
  v: Bar[T] = None
145
148
  `,
@@ -183,7 +183,10 @@ describe("Python Variable", () => {
183
183
 
184
184
  `,
185
185
  "usage.py": `
186
- from classes import MyClass
186
+ from typing import TYPE_CHECKING
187
+
188
+ if TYPE_CHECKING:
189
+ from classes import MyClass
187
190
 
188
191
  my_var: MyClass = None
189
192
  `,
package/vitest.config.ts CHANGED
@@ -2,6 +2,14 @@ import alloyPlugin from "@alloy-js/rollup-plugin";
2
2
  import { defineConfig } from "vitest/config";
3
3
 
4
4
  export default defineConfig({
5
+ resolve: {
6
+ conditions: ["source"],
7
+ },
8
+ ssr: {
9
+ resolve: {
10
+ conditions: ["source"],
11
+ },
12
+ },
5
13
  esbuild: {
6
14
  jsx: "preserve",
7
15
  sourcemap: "both",