@typespec/emitter-framework 0.15.0-dev.3 → 0.15.0-dev.4

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 (253) hide show
  1. package/CHANGELOG.md +1 -16
  2. package/dist/src/python/builtins.d.ts +14 -0
  3. package/dist/src/python/builtins.d.ts.map +1 -0
  4. package/dist/src/python/builtins.js +29 -0
  5. package/dist/src/python/builtins.js.map +1 -0
  6. package/dist/src/python/components/array-expression/array-expression.d.ts +6 -0
  7. package/dist/src/python/components/array-expression/array-expression.d.ts.map +1 -0
  8. package/dist/src/python/components/array-expression/array-expression.js +11 -0
  9. package/dist/src/python/components/array-expression/array-expression.js.map +1 -0
  10. package/dist/src/python/components/array-expression/array-expression.test.d.ts +2 -0
  11. package/dist/src/python/components/array-expression/array-expression.test.d.ts.map +1 -0
  12. package/dist/src/python/components/array-expression/array-expression.test.js +19 -0
  13. package/dist/src/python/components/array-expression/array-expression.test.js.map +1 -0
  14. package/dist/src/python/components/array-expression/index.d.ts +2 -0
  15. package/dist/src/python/components/array-expression/index.d.ts.map +1 -0
  16. package/dist/src/python/components/array-expression/index.js +2 -0
  17. package/dist/src/python/components/array-expression/index.js.map +1 -0
  18. package/dist/src/python/components/atom/atom.d.ts +33 -0
  19. package/dist/src/python/components/atom/atom.d.ts.map +1 -0
  20. package/dist/src/python/components/atom/atom.js +88 -0
  21. package/dist/src/python/components/atom/atom.js.map +1 -0
  22. package/dist/src/python/components/atom/atom.test.d.ts +2 -0
  23. package/dist/src/python/components/atom/atom.test.d.ts.map +1 -0
  24. package/dist/src/python/components/atom/atom.test.js +224 -0
  25. package/dist/src/python/components/atom/atom.test.js.map +1 -0
  26. package/dist/src/python/components/atom/index.d.ts +2 -0
  27. package/dist/src/python/components/atom/index.d.ts.map +1 -0
  28. package/dist/src/python/components/atom/index.js +2 -0
  29. package/dist/src/python/components/atom/index.js.map +1 -0
  30. package/dist/src/python/components/class-declaration/class-bases.d.ts +45 -0
  31. package/dist/src/python/components/class-declaration/class-bases.d.ts.map +1 -0
  32. package/dist/src/python/components/class-declaration/class-bases.js +84 -0
  33. package/dist/src/python/components/class-declaration/class-bases.js.map +1 -0
  34. package/dist/src/python/components/class-declaration/class-body.d.ts +16 -0
  35. package/dist/src/python/components/class-declaration/class-body.d.ts.map +1 -0
  36. package/dist/src/python/components/class-declaration/class-body.js +52 -0
  37. package/dist/src/python/components/class-declaration/class-body.js.map +1 -0
  38. package/dist/src/python/components/class-declaration/class-declaration.d.ts +23 -0
  39. package/dist/src/python/components/class-declaration/class-declaration.d.ts.map +1 -0
  40. package/dist/src/python/components/class-declaration/class-declaration.js +118 -0
  41. package/dist/src/python/components/class-declaration/class-declaration.js.map +1 -0
  42. package/dist/src/python/components/class-declaration/class-declaration.test.d.ts +2 -0
  43. package/dist/src/python/components/class-declaration/class-declaration.test.d.ts.map +1 -0
  44. package/dist/src/python/components/class-declaration/class-declaration.test.js +1527 -0
  45. package/dist/src/python/components/class-declaration/class-declaration.test.js.map +1 -0
  46. package/dist/src/python/components/class-declaration/class-member.d.ts +16 -0
  47. package/dist/src/python/components/class-declaration/class-member.d.ts.map +1 -0
  48. package/dist/src/python/components/class-declaration/class-member.js +71 -0
  49. package/dist/src/python/components/class-declaration/class-member.js.map +1 -0
  50. package/dist/src/python/components/class-declaration/class-member.test.d.ts +2 -0
  51. package/dist/src/python/components/class-declaration/class-member.test.d.ts.map +1 -0
  52. package/dist/src/python/components/class-declaration/class-member.test.js +202 -0
  53. package/dist/src/python/components/class-declaration/class-member.test.js.map +1 -0
  54. package/dist/src/python/components/class-declaration/class-method.d.ts +22 -0
  55. package/dist/src/python/components/class-declaration/class-method.d.ts.map +1 -0
  56. package/dist/src/python/components/class-declaration/class-method.js +76 -0
  57. package/dist/src/python/components/class-declaration/class-method.js.map +1 -0
  58. package/dist/src/python/components/class-declaration/class-method.test.d.ts +2 -0
  59. package/dist/src/python/components/class-declaration/class-method.test.d.ts.map +1 -0
  60. package/dist/src/python/components/class-declaration/class-method.test.js +298 -0
  61. package/dist/src/python/components/class-declaration/class-method.test.js.map +1 -0
  62. package/dist/src/python/components/class-declaration/index.d.ts +7 -0
  63. package/dist/src/python/components/class-declaration/index.d.ts.map +1 -0
  64. package/dist/src/python/components/class-declaration/index.js +7 -0
  65. package/dist/src/python/components/class-declaration/index.js.map +1 -0
  66. package/dist/src/python/components/class-declaration/primitive-initializer.d.ts +22 -0
  67. package/dist/src/python/components/class-declaration/primitive-initializer.d.ts.map +1 -0
  68. package/dist/src/python/components/class-declaration/primitive-initializer.js +67 -0
  69. package/dist/src/python/components/class-declaration/primitive-initializer.js.map +1 -0
  70. package/dist/src/python/components/doc-element/doc-element.d.ts +46 -0
  71. package/dist/src/python/components/doc-element/doc-element.d.ts.map +1 -0
  72. package/dist/src/python/components/doc-element/doc-element.js +59 -0
  73. package/dist/src/python/components/doc-element/doc-element.js.map +1 -0
  74. package/dist/src/python/components/doc-element/index.d.ts +2 -0
  75. package/dist/src/python/components/doc-element/index.d.ts.map +1 -0
  76. package/dist/src/python/components/doc-element/index.js +2 -0
  77. package/dist/src/python/components/doc-element/index.js.map +1 -0
  78. package/dist/src/python/components/enum-declaration/enum-declaration.d.ts +8 -0
  79. package/dist/src/python/components/enum-declaration/enum-declaration.d.ts.map +1 -0
  80. package/dist/src/python/components/enum-declaration/enum-declaration.js +80 -0
  81. package/dist/src/python/components/enum-declaration/enum-declaration.js.map +1 -0
  82. package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts +2 -0
  83. package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts.map +1 -0
  84. package/dist/src/python/components/enum-declaration/enum-declaration.test.js +344 -0
  85. package/dist/src/python/components/enum-declaration/enum-declaration.test.js.map +1 -0
  86. package/dist/src/python/components/enum-declaration/enum-member.d.ts +9 -0
  87. package/dist/src/python/components/enum-declaration/enum-member.d.ts.map +1 -0
  88. package/dist/src/python/components/enum-declaration/enum-member.js +22 -0
  89. package/dist/src/python/components/enum-declaration/enum-member.js.map +1 -0
  90. package/dist/src/python/components/enum-declaration/index.d.ts +3 -0
  91. package/dist/src/python/components/enum-declaration/index.d.ts.map +1 -0
  92. package/dist/src/python/components/enum-declaration/index.js +3 -0
  93. package/dist/src/python/components/enum-declaration/index.js.map +1 -0
  94. package/dist/src/python/components/function-declaration/function-declaration.d.ts +24 -0
  95. package/dist/src/python/components/function-declaration/function-declaration.d.ts.map +1 -0
  96. package/dist/src/python/components/function-declaration/function-declaration.js +68 -0
  97. package/dist/src/python/components/function-declaration/function-declaration.js.map +1 -0
  98. package/dist/src/python/components/function-declaration/function-declaration.test.d.ts +2 -0
  99. package/dist/src/python/components/function-declaration/function-declaration.test.d.ts.map +1 -0
  100. package/dist/src/python/components/function-declaration/function-declaration.test.js +682 -0
  101. package/dist/src/python/components/function-declaration/function-declaration.test.js.map +1 -0
  102. package/dist/src/python/components/function-declaration/index.d.ts +2 -0
  103. package/dist/src/python/components/function-declaration/index.d.ts.map +1 -0
  104. package/dist/src/python/components/function-declaration/index.js +2 -0
  105. package/dist/src/python/components/function-declaration/index.js.map +1 -0
  106. package/dist/src/python/components/index.d.ts +12 -0
  107. package/dist/src/python/components/index.d.ts.map +1 -0
  108. package/dist/src/python/components/index.js +12 -0
  109. package/dist/src/python/components/index.js.map +1 -0
  110. package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts +25 -0
  111. package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts.map +1 -0
  112. package/dist/src/python/components/protocol-declaration/callable-parameters.js +33 -0
  113. package/dist/src/python/components/protocol-declaration/callable-parameters.js.map +1 -0
  114. package/dist/src/python/components/protocol-declaration/index.d.ts +3 -0
  115. package/dist/src/python/components/protocol-declaration/index.d.ts.map +1 -0
  116. package/dist/src/python/components/protocol-declaration/index.js +3 -0
  117. package/dist/src/python/components/protocol-declaration/index.js.map +1 -0
  118. package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts +8 -0
  119. package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts.map +1 -0
  120. package/dist/src/python/components/protocol-declaration/protocol-declaration.js +86 -0
  121. package/dist/src/python/components/protocol-declaration/protocol-declaration.js.map +1 -0
  122. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts +2 -0
  123. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts.map +1 -0
  124. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js +117 -0
  125. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js.map +1 -0
  126. package/dist/src/python/components/record-expression/index.d.ts +2 -0
  127. package/dist/src/python/components/record-expression/index.d.ts.map +1 -0
  128. package/dist/src/python/components/record-expression/index.js +2 -0
  129. package/dist/src/python/components/record-expression/index.js.map +1 -0
  130. package/dist/src/python/components/record-expression/record-expression.d.ts +6 -0
  131. package/dist/src/python/components/record-expression/record-expression.d.ts.map +1 -0
  132. package/dist/src/python/components/record-expression/record-expression.js +13 -0
  133. package/dist/src/python/components/record-expression/record-expression.js.map +1 -0
  134. package/dist/src/python/components/record-expression/record-expression.test.d.ts +2 -0
  135. package/dist/src/python/components/record-expression/record-expression.test.d.ts.map +1 -0
  136. package/dist/src/python/components/record-expression/record-expression.test.js +19 -0
  137. package/dist/src/python/components/record-expression/record-expression.test.js.map +1 -0
  138. package/dist/src/python/components/type-alias-declaration/index.d.ts +2 -0
  139. package/dist/src/python/components/type-alias-declaration/index.d.ts.map +1 -0
  140. package/dist/src/python/components/type-alias-declaration/index.js +2 -0
  141. package/dist/src/python/components/type-alias-declaration/index.js.map +1 -0
  142. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts +16 -0
  143. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts.map +1 -0
  144. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js +75 -0
  145. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js.map +1 -0
  146. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts +2 -0
  147. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts.map +1 -0
  148. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js +140 -0
  149. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js.map +1 -0
  150. package/dist/src/python/components/type-declaration/index.d.ts +2 -0
  151. package/dist/src/python/components/type-declaration/index.d.ts.map +1 -0
  152. package/dist/src/python/components/type-declaration/index.js +2 -0
  153. package/dist/src/python/components/type-declaration/index.js.map +1 -0
  154. package/dist/src/python/components/type-declaration/type-declaration.d.ts +11 -0
  155. package/dist/src/python/components/type-declaration/type-declaration.d.ts.map +1 -0
  156. package/dist/src/python/components/type-declaration/type-declaration.js +31 -0
  157. package/dist/src/python/components/type-declaration/type-declaration.js.map +1 -0
  158. package/dist/src/python/components/type-declaration/type-declaration.test.d.ts +2 -0
  159. package/dist/src/python/components/type-declaration/type-declaration.test.d.ts.map +1 -0
  160. package/dist/src/python/components/type-declaration/type-declaration.test.js +69 -0
  161. package/dist/src/python/components/type-declaration/type-declaration.test.js.map +1 -0
  162. package/dist/src/python/components/type-expression/index.d.ts +2 -0
  163. package/dist/src/python/components/type-expression/index.d.ts.map +1 -0
  164. package/dist/src/python/components/type-expression/index.js +2 -0
  165. package/dist/src/python/components/type-expression/index.js.map +1 -0
  166. package/dist/src/python/components/type-expression/type-expression.d.ts +12 -0
  167. package/dist/src/python/components/type-expression/type-expression.d.ts.map +1 -0
  168. package/dist/src/python/components/type-expression/type-expression.js +348 -0
  169. package/dist/src/python/components/type-expression/type-expression.js.map +1 -0
  170. package/dist/src/python/components/type-expression/type-expression.test.d.ts +2 -0
  171. package/dist/src/python/components/type-expression/type-expression.test.d.ts.map +1 -0
  172. package/dist/src/python/components/type-expression/type-expression.test.js +503 -0
  173. package/dist/src/python/components/type-expression/type-expression.test.js.map +1 -0
  174. package/dist/src/python/index.d.ts +4 -0
  175. package/dist/src/python/index.d.ts.map +1 -0
  176. package/dist/src/python/index.js +4 -0
  177. package/dist/src/python/index.js.map +1 -0
  178. package/dist/src/python/lib.d.ts +68 -0
  179. package/dist/src/python/lib.d.ts.map +1 -0
  180. package/dist/src/python/lib.js +38 -0
  181. package/dist/src/python/lib.js.map +1 -0
  182. package/dist/src/python/test-utils.d.ts +8 -0
  183. package/dist/src/python/test-utils.d.ts.map +1 -0
  184. package/dist/src/python/test-utils.js +25 -0
  185. package/dist/src/python/test-utils.js.map +1 -0
  186. package/dist/src/python/utils/index.d.ts +4 -0
  187. package/dist/src/python/utils/index.d.ts.map +1 -0
  188. package/dist/src/python/utils/index.js +4 -0
  189. package/dist/src/python/utils/index.js.map +1 -0
  190. package/dist/src/python/utils/operation.d.ts +27 -0
  191. package/dist/src/python/utils/operation.d.ts.map +1 -0
  192. package/dist/src/python/utils/operation.js +139 -0
  193. package/dist/src/python/utils/operation.js.map +1 -0
  194. package/dist/src/python/utils/refkey.d.ts +23 -0
  195. package/dist/src/python/utils/refkey.d.ts.map +1 -0
  196. package/dist/src/python/utils/refkey.js +36 -0
  197. package/dist/src/python/utils/refkey.js.map +1 -0
  198. package/dist/src/python/utils/type.d.ts +19 -0
  199. package/dist/src/python/utils/type.d.ts.map +1 -0
  200. package/dist/src/python/utils/type.js +24 -0
  201. package/dist/src/python/utils/type.js.map +1 -0
  202. package/package.json +9 -1
  203. package/package.json.bak +10 -1
  204. package/src/python/builtins.ts +43 -0
  205. package/src/python/components/array-expression/array-expression.test.tsx +14 -0
  206. package/src/python/components/array-expression/array-expression.tsx +11 -0
  207. package/src/python/components/array-expression/index.ts +1 -0
  208. package/src/python/components/atom/atom.test.tsx +244 -0
  209. package/src/python/components/atom/atom.tsx +95 -0
  210. package/src/python/components/atom/index.ts +1 -0
  211. package/src/python/components/class-declaration/class-bases.tsx +92 -0
  212. package/src/python/components/class-declaration/class-body.tsx +56 -0
  213. package/src/python/components/class-declaration/class-declaration.test.tsx +1414 -0
  214. package/src/python/components/class-declaration/class-declaration.tsx +116 -0
  215. package/src/python/components/class-declaration/class-member.test.tsx +194 -0
  216. package/src/python/components/class-declaration/class-member.tsx +67 -0
  217. package/src/python/components/class-declaration/class-method.test.tsx +250 -0
  218. package/src/python/components/class-declaration/class-method.tsx +97 -0
  219. package/src/python/components/class-declaration/index.ts +6 -0
  220. package/src/python/components/class-declaration/primitive-initializer.tsx +62 -0
  221. package/src/python/components/doc-element/doc-element.tsx +83 -0
  222. package/src/python/components/doc-element/index.ts +1 -0
  223. package/src/python/components/enum-declaration/enum-declaration.test.tsx +319 -0
  224. package/src/python/components/enum-declaration/enum-declaration.tsx +77 -0
  225. package/src/python/components/enum-declaration/enum-member.tsx +21 -0
  226. package/src/python/components/enum-declaration/index.ts +2 -0
  227. package/src/python/components/function-declaration/function-declaration.test.tsx +582 -0
  228. package/src/python/components/function-declaration/function-declaration.tsx +90 -0
  229. package/src/python/components/function-declaration/index.ts +1 -0
  230. package/src/python/components/index.ts +11 -0
  231. package/src/python/components/protocol-declaration/callable-parameters.tsx +44 -0
  232. package/src/python/components/protocol-declaration/index.ts +2 -0
  233. package/src/python/components/protocol-declaration/protocol-declaration.test.tsx +106 -0
  234. package/src/python/components/protocol-declaration/protocol-declaration.tsx +73 -0
  235. package/src/python/components/record-expression/index.ts +1 -0
  236. package/src/python/components/record-expression/record-expression.test.tsx +14 -0
  237. package/src/python/components/record-expression/record-expression.tsx +13 -0
  238. package/src/python/components/type-alias-declaration/index.ts +1 -0
  239. package/src/python/components/type-alias-declaration/type-alias-declaration.test.tsx +117 -0
  240. package/src/python/components/type-alias-declaration/type-alias-declaration.tsx +67 -0
  241. package/src/python/components/type-declaration/index.ts +1 -0
  242. package/src/python/components/type-declaration/type-declaration.test.tsx +58 -0
  243. package/src/python/components/type-declaration/type-declaration.tsx +26 -0
  244. package/src/python/components/type-expression/index.ts +1 -0
  245. package/src/python/components/type-expression/type-expression.test.tsx +463 -0
  246. package/src/python/components/type-expression/type-expression.tsx +333 -0
  247. package/src/python/index.ts +3 -0
  248. package/src/python/lib.ts +40 -0
  249. package/src/python/test-utils.tsx +31 -0
  250. package/src/python/utils/index.ts +3 -0
  251. package/src/python/utils/operation.ts +161 -0
  252. package/src/python/utils/refkey.ts +36 -0
  253. package/src/python/utils/type.ts +31 -0
@@ -0,0 +1,463 @@
1
+ import { Tester } from "#test/test-host.js";
2
+ import { d } from "@alloy-js/core/testing";
3
+ import { t } from "@typespec/compiler/testing";
4
+ import { describe, expect, it } from "vitest";
5
+ import { getOutput } from "../../test-utils.js";
6
+ import { EnumDeclaration } from "../enum-declaration/enum-declaration.js";
7
+ import { TypeExpression } from "./type-expression.js";
8
+
9
+ describe("map Typespec types to Python built-in types", () => {
10
+ it.each([
11
+ ["unknown", "Any", "from typing import Any"],
12
+ ["string", "str"],
13
+ ["boolean", "bool"],
14
+ ["null", "None"],
15
+ ["void", "None"],
16
+ ["never", "Never", "from typing import Never"],
17
+ ["bytes", "bytes"],
18
+ ["numeric", "number"],
19
+ ["integer", "int"],
20
+ ["float", "float"],
21
+ ["decimal", "Decimal", "from decimal import Decimal"],
22
+ ["decimal128", "Decimal", "from decimal import Decimal"],
23
+ ["int64", "int"],
24
+ ["int32", "int"],
25
+ ["int16", "int"],
26
+ ["int8", "int"],
27
+ ["safeint", "int"],
28
+ ["uint64", "int"],
29
+ ["uint32", "int"],
30
+ ["uint16", "int"],
31
+ ["uint8", "int"],
32
+ ["float32", "float"],
33
+ ["float64", "float"],
34
+ ["plainDate", "str"],
35
+ ["plainTime", "str"],
36
+ ["utcDateTime", "datetime", "from datetime import datetime"],
37
+ ["offsetDateTime", "str"],
38
+ ["duration", "str"],
39
+ ["url", "str"],
40
+ ])("%s => %s", async (tspType, pythonType, extraImport = "") => {
41
+ const { program, Type } = await Tester.compile(t.code`
42
+ alias ${t.type("Type")} = ${t.type(tspType)};
43
+ `);
44
+
45
+ expect(getOutput(program, [<TypeExpression type={Type} />])).toRenderTo(d`
46
+ ${extraImport ? `${extraImport}\n\n\n` : ""}${pythonType}
47
+ `);
48
+ });
49
+ });
50
+
51
+ describe("map scalar to Python types", () => {
52
+ it("Email => str (scalars are inlined to base type)", async () => {
53
+ const { program, Email } = await Tester.compile(t.code`
54
+ scalar ${t.scalar("Email")} extends string;
55
+ `);
56
+
57
+ expect(getOutput(program, [<TypeExpression type={Email} />])).toRenderTo(d`
58
+ str
59
+ `);
60
+ });
61
+
62
+ it("PhoneNumber => str (scalar in model property is inlined)", async () => {
63
+ const { program, _ } = await Tester.compile(t.code`
64
+ scalar PhoneNumber extends string;
65
+
66
+ model ${t.model("Widget")} {
67
+ phone: PhoneNumber;
68
+ }
69
+ `);
70
+
71
+ const phoneProperty = program.resolveTypeReference("Widget")[0]!;
72
+ const phoneProp = (phoneProperty as any).properties.get("phone");
73
+
74
+ expect(getOutput(program, [<TypeExpression type={phoneProp.type} />])).toRenderTo(d`
75
+ str
76
+ `);
77
+ });
78
+ });
79
+
80
+ describe("map tuple to Python types", () => {
81
+ it("[int32, int32] => tuple[int, int]", async () => {
82
+ const { program, Tuple } = await Tester.compile(t.code`
83
+ alias ${t.type("Tuple")} = [int32, int32];
84
+ `);
85
+
86
+ expect(getOutput(program, [<TypeExpression type={Tuple} />])).toRenderTo(d`
87
+ tuple[int, int]
88
+ `);
89
+ });
90
+ });
91
+
92
+ describe("map operation (function type) to typing.Callable", () => {
93
+ it("op f(a: int32, b: string): void => Callable[[int, str], None]", async () => {
94
+ const { program, f } = await Tester.compile(t.code`
95
+ op ${t.op("f")}(a: int32, b: string): void;
96
+ `);
97
+
98
+ expect(getOutput(program, [<TypeExpression type={f} />])).toRenderTo(d`
99
+ from typing import Callable
100
+
101
+
102
+ Callable[[int, str], None]
103
+ `);
104
+ });
105
+
106
+ it("op g(): int32 => Callable[[], int]", async () => {
107
+ const { program, g } = await Tester.compile(t.code`
108
+ op ${t.op("g")}(): int32;
109
+ `);
110
+
111
+ expect(getOutput(program, [<TypeExpression type={g} />])).toRenderTo(d`
112
+ from typing import Callable
113
+
114
+
115
+ Callable[[], int]
116
+ `);
117
+ });
118
+ });
119
+
120
+ describe("correctly solves a ModelProperty to Python types", () => {
121
+ it("[int32, int32] => tuple[int, int]", async () => {
122
+ const { program, tupleProperty } = await Tester.compile(t.code`
123
+ model Test {
124
+ ${t.modelProperty("tupleProperty")}: [int32, int32];
125
+ }
126
+ `);
127
+
128
+ expect(getOutput(program, [<TypeExpression type={tupleProperty} />])).toRenderTo(d`
129
+ tuple[int, int]
130
+ `);
131
+ });
132
+ });
133
+
134
+ describe("handles UnionVariant types", () => {
135
+ it("renders named union variant with literal value as Literal[Union.MEMBER]", async () => {
136
+ const { program, Color } = await Tester.compile(t.code`
137
+ union ${t.union("Color")} {
138
+ red: "red",
139
+ blue: "blue",
140
+ }
141
+
142
+ model Widget {
143
+ color: Color.red;
144
+ }
145
+ `);
146
+
147
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
148
+ const colorProperty = Widget.properties.get("color");
149
+
150
+ expect(
151
+ getOutput(program, [
152
+ <EnumDeclaration type={Color} />,
153
+ <TypeExpression type={colorProperty.type} />,
154
+ ]),
155
+ ).toRenderTo(d`
156
+ from enum import StrEnum
157
+ from typing import Literal
158
+
159
+
160
+ class Color(StrEnum):
161
+ RED = "red"
162
+ BLUE = "blue"
163
+
164
+
165
+ Literal[Color.RED]
166
+ `);
167
+ });
168
+
169
+ it("renders named union variant with integer literal as Literal[Union.MEMBER]", async () => {
170
+ const { program, Status } = await Tester.compile(t.code`
171
+ union ${t.union("Status")} {
172
+ active: 1,
173
+ inactive: 0,
174
+ }
175
+
176
+ model Widget {
177
+ status: Status.active;
178
+ }
179
+ `);
180
+
181
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
182
+ const statusProperty = Widget.properties.get("status");
183
+
184
+ expect(
185
+ getOutput(program, [
186
+ <EnumDeclaration type={Status} />,
187
+ <TypeExpression type={statusProperty.type} />,
188
+ ]),
189
+ ).toRenderTo(d`
190
+ from enum import IntEnum
191
+ from typing import Literal
192
+
193
+
194
+ class Status(IntEnum):
195
+ ACTIVE = 1
196
+ INACTIVE = 0
197
+
198
+
199
+ Literal[Status.ACTIVE]
200
+ `);
201
+ });
202
+
203
+ it("unwraps union variant with non-literal type to reveal the inner type", async () => {
204
+ const { program } = await Tester.compile(t.code`
205
+ union Status {
206
+ active: string,
207
+ inactive: int32,
208
+ }
209
+
210
+ model Widget {
211
+ status: Status.inactive;
212
+ }
213
+ `);
214
+
215
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
216
+ const statusProperty = Widget.properties.get("status");
217
+
218
+ // The UnionVariant should unwrap to reveal int32 (non-literal type)
219
+ expect(statusProperty.type.kind).toBe("UnionVariant");
220
+ expect(getOutput(program, [<TypeExpression type={statusProperty.type} />])).toRenderTo(d`
221
+ int
222
+ `);
223
+ });
224
+
225
+ it("handles named union variant in function return type", async () => {
226
+ const { program, Result } = await Tester.compile(t.code`
227
+ union ${t.union("Result")} {
228
+ success: "success",
229
+ failure: "failure",
230
+ }
231
+
232
+ op getResult(): Result.success;
233
+ `);
234
+
235
+ const getResult = program.resolveTypeReference("getResult")[0]! as any;
236
+ const returnType = getResult.returnType;
237
+
238
+ expect(
239
+ getOutput(program, [<EnumDeclaration type={Result} />, <TypeExpression type={returnType} />]),
240
+ ).toRenderTo(d`
241
+ from enum import StrEnum
242
+ from typing import Literal
243
+
244
+
245
+ class Result(StrEnum):
246
+ SUCCESS = "success"
247
+ FAILURE = "failure"
248
+
249
+
250
+ Literal[Result.SUCCESS]
251
+ `);
252
+ });
253
+
254
+ it("unwraps nested union variant with non-literal inner types", async () => {
255
+ const { program } = await Tester.compile(t.code`
256
+ union Inner {
257
+ a: string,
258
+ b: int32,
259
+ }
260
+
261
+ union Outer {
262
+ x: Inner.a,
263
+ y: Inner.b,
264
+ }
265
+
266
+ model Widget {
267
+ value: Outer.x;
268
+ }
269
+ `);
270
+
271
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
272
+ const valueProperty = Widget.properties.get("value");
273
+
274
+ // Inner.a has type `string` (not a literal), so it unwraps
275
+ expect(getOutput(program, [<TypeExpression type={valueProperty.type} />])).toRenderTo(d`
276
+ str
277
+ `);
278
+ });
279
+ });
280
+
281
+ describe("handles literal types", () => {
282
+ it("renders union of string literals as Literal[...]", async () => {
283
+ const { program } = await Tester.compile(t.code`
284
+ model Widget {
285
+ status: "active" | "inactive" | "pending";
286
+ }
287
+ `);
288
+
289
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
290
+ const statusProperty = Widget.properties.get("status");
291
+
292
+ expect(getOutput(program, [<TypeExpression type={statusProperty.type} />])).toRenderTo(d`
293
+ from typing import Literal
294
+
295
+
296
+ Literal["active", "inactive", "pending"]
297
+ `);
298
+ });
299
+
300
+ it("renders union of integer literals as Literal[...]", async () => {
301
+ const { program } = await Tester.compile(t.code`
302
+ model Widget {
303
+ priority: 1 | 2 | 3;
304
+ }
305
+ `);
306
+
307
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
308
+ const priorityProperty = Widget.properties.get("priority");
309
+
310
+ expect(getOutput(program, [<TypeExpression type={priorityProperty.type} />])).toRenderTo(d`
311
+ from typing import Literal
312
+
313
+
314
+ Literal[1, 2, 3]
315
+ `);
316
+ });
317
+
318
+ it("renders union of boolean literals as Literal[...]", async () => {
319
+ const { program } = await Tester.compile(t.code`
320
+ model Widget {
321
+ flag: true | false;
322
+ }
323
+ `);
324
+
325
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
326
+ const flagProperty = Widget.properties.get("flag");
327
+
328
+ expect(getOutput(program, [<TypeExpression type={flagProperty.type} />])).toRenderTo(d`
329
+ from typing import Literal
330
+
331
+
332
+ Literal[True, False]
333
+ `);
334
+ });
335
+
336
+ it("renders mixed literal union as Literal[...]", async () => {
337
+ const { program } = await Tester.compile(t.code`
338
+ model Widget {
339
+ value: "auto" | 0 | 100;
340
+ }
341
+ `);
342
+
343
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
344
+ const valueProperty = Widget.properties.get("value");
345
+
346
+ expect(getOutput(program, [<TypeExpression type={valueProperty.type} />])).toRenderTo(d`
347
+ from typing import Literal
348
+
349
+
350
+ Literal["auto", 0, 100]
351
+ `);
352
+ });
353
+
354
+ it("renders function returning literal union as Literal[...]", async () => {
355
+ const { program } = await Tester.compile(t.code`
356
+ op getStatus(): "success" | "failure";
357
+ `);
358
+
359
+ const getStatus = program.resolveTypeReference("getStatus")[0]! as any;
360
+
361
+ expect(getOutput(program, [<TypeExpression type={getStatus.returnType} />])).toRenderTo(d`
362
+ from typing import Literal
363
+
364
+
365
+ Literal["success", "failure"]
366
+ `);
367
+ });
368
+
369
+ it("renders single string literal as Literal[...]", async () => {
370
+ const { program } = await Tester.compile(t.code`
371
+ model Widget {
372
+ constant: "fixed-value";
373
+ }
374
+ `);
375
+
376
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
377
+ const constantProperty = Widget.properties.get("constant");
378
+
379
+ expect(getOutput(program, [<TypeExpression type={constantProperty.type} />])).toRenderTo(d`
380
+ from typing import Literal
381
+
382
+
383
+ Literal["fixed-value"]
384
+ `);
385
+ });
386
+
387
+ it("renders function returning single string literal as Literal[...]", async () => {
388
+ const { program } = await Tester.compile(t.code`
389
+ op getSteve(): "steve";
390
+ `);
391
+
392
+ const getSteve = program.resolveTypeReference("getSteve")[0]! as any;
393
+
394
+ expect(getOutput(program, [<TypeExpression type={getSteve.returnType} />])).toRenderTo(d`
395
+ from typing import Literal
396
+
397
+
398
+ Literal["steve"]
399
+ `);
400
+ });
401
+
402
+ it("renders single numeric literal as Literal[...]", async () => {
403
+ const { program } = await Tester.compile(t.code`
404
+ op getAnswer(): 42;
405
+ `);
406
+
407
+ const getAnswer = program.resolveTypeReference("getAnswer")[0]! as any;
408
+
409
+ expect(getOutput(program, [<TypeExpression type={getAnswer.returnType} />])).toRenderTo(d`
410
+ from typing import Literal
411
+
412
+
413
+ Literal[42]
414
+ `);
415
+ });
416
+
417
+ it("renders single boolean literal as Literal[...]", async () => {
418
+ const { program } = await Tester.compile(t.code`
419
+ op isEnabled(): true;
420
+ `);
421
+
422
+ const isEnabled = program.resolveTypeReference("isEnabled")[0]! as any;
423
+
424
+ expect(getOutput(program, [<TypeExpression type={isEnabled.returnType} />])).toRenderTo(d`
425
+ from typing import Literal
426
+
427
+
428
+ Literal[True]
429
+ `);
430
+ });
431
+
432
+ it("renders union with non-literal types as regular union", async () => {
433
+ const { program } = await Tester.compile(t.code`
434
+ model Widget {
435
+ value: string | int32;
436
+ }
437
+ `);
438
+
439
+ const Widget = program.resolveTypeReference("Widget")[0]! as any;
440
+ const valueProperty = Widget.properties.get("value");
441
+
442
+ // Mixed literal and non-literal types render as regular union
443
+ expect(getOutput(program, [<TypeExpression type={valueProperty.type} />])).toRenderTo(d`
444
+ str | int
445
+ `);
446
+ });
447
+
448
+ it("renders function with literal parameter type", async () => {
449
+ const { program } = await Tester.compile(t.code`
450
+ op setMode(mode: "auto" | "manual"): void;
451
+ `);
452
+
453
+ const setMode = program.resolveTypeReference("setMode")[0]! as any;
454
+ const modeParam = setMode.parameters.properties.get("mode");
455
+
456
+ expect(getOutput(program, [<TypeExpression type={modeParam.type} />])).toRenderTo(d`
457
+ from typing import Literal
458
+
459
+
460
+ Literal["auto", "manual"]
461
+ `);
462
+ });
463
+ });