@typespec/emitter-framework 0.15.0-dev.2 → 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 (259) hide show
  1. package/CHANGELOG.md +1 -16
  2. package/dist/src/core/components/overrides/component-overrides.d.ts.map +1 -1
  3. package/dist/src/core/components/overrides/component-overrides.js.map +1 -1
  4. package/dist/src/python/builtins.d.ts +14 -0
  5. package/dist/src/python/builtins.d.ts.map +1 -0
  6. package/dist/src/python/builtins.js +29 -0
  7. package/dist/src/python/builtins.js.map +1 -0
  8. package/dist/src/python/components/array-expression/array-expression.d.ts +6 -0
  9. package/dist/src/python/components/array-expression/array-expression.d.ts.map +1 -0
  10. package/dist/src/python/components/array-expression/array-expression.js +11 -0
  11. package/dist/src/python/components/array-expression/array-expression.js.map +1 -0
  12. package/dist/src/python/components/array-expression/array-expression.test.d.ts +2 -0
  13. package/dist/src/python/components/array-expression/array-expression.test.d.ts.map +1 -0
  14. package/dist/src/python/components/array-expression/array-expression.test.js +19 -0
  15. package/dist/src/python/components/array-expression/array-expression.test.js.map +1 -0
  16. package/dist/src/python/components/array-expression/index.d.ts +2 -0
  17. package/dist/src/python/components/array-expression/index.d.ts.map +1 -0
  18. package/dist/src/python/components/array-expression/index.js +2 -0
  19. package/dist/src/python/components/array-expression/index.js.map +1 -0
  20. package/dist/src/python/components/atom/atom.d.ts +33 -0
  21. package/dist/src/python/components/atom/atom.d.ts.map +1 -0
  22. package/dist/src/python/components/atom/atom.js +88 -0
  23. package/dist/src/python/components/atom/atom.js.map +1 -0
  24. package/dist/src/python/components/atom/atom.test.d.ts +2 -0
  25. package/dist/src/python/components/atom/atom.test.d.ts.map +1 -0
  26. package/dist/src/python/components/atom/atom.test.js +224 -0
  27. package/dist/src/python/components/atom/atom.test.js.map +1 -0
  28. package/dist/src/python/components/atom/index.d.ts +2 -0
  29. package/dist/src/python/components/atom/index.d.ts.map +1 -0
  30. package/dist/src/python/components/atom/index.js +2 -0
  31. package/dist/src/python/components/atom/index.js.map +1 -0
  32. package/dist/src/python/components/class-declaration/class-bases.d.ts +45 -0
  33. package/dist/src/python/components/class-declaration/class-bases.d.ts.map +1 -0
  34. package/dist/src/python/components/class-declaration/class-bases.js +84 -0
  35. package/dist/src/python/components/class-declaration/class-bases.js.map +1 -0
  36. package/dist/src/python/components/class-declaration/class-body.d.ts +16 -0
  37. package/dist/src/python/components/class-declaration/class-body.d.ts.map +1 -0
  38. package/dist/src/python/components/class-declaration/class-body.js +52 -0
  39. package/dist/src/python/components/class-declaration/class-body.js.map +1 -0
  40. package/dist/src/python/components/class-declaration/class-declaration.d.ts +23 -0
  41. package/dist/src/python/components/class-declaration/class-declaration.d.ts.map +1 -0
  42. package/dist/src/python/components/class-declaration/class-declaration.js +118 -0
  43. package/dist/src/python/components/class-declaration/class-declaration.js.map +1 -0
  44. package/dist/src/python/components/class-declaration/class-declaration.test.d.ts +2 -0
  45. package/dist/src/python/components/class-declaration/class-declaration.test.d.ts.map +1 -0
  46. package/dist/src/python/components/class-declaration/class-declaration.test.js +1527 -0
  47. package/dist/src/python/components/class-declaration/class-declaration.test.js.map +1 -0
  48. package/dist/src/python/components/class-declaration/class-member.d.ts +16 -0
  49. package/dist/src/python/components/class-declaration/class-member.d.ts.map +1 -0
  50. package/dist/src/python/components/class-declaration/class-member.js +71 -0
  51. package/dist/src/python/components/class-declaration/class-member.js.map +1 -0
  52. package/dist/src/python/components/class-declaration/class-member.test.d.ts +2 -0
  53. package/dist/src/python/components/class-declaration/class-member.test.d.ts.map +1 -0
  54. package/dist/src/python/components/class-declaration/class-member.test.js +202 -0
  55. package/dist/src/python/components/class-declaration/class-member.test.js.map +1 -0
  56. package/dist/src/python/components/class-declaration/class-method.d.ts +22 -0
  57. package/dist/src/python/components/class-declaration/class-method.d.ts.map +1 -0
  58. package/dist/src/python/components/class-declaration/class-method.js +76 -0
  59. package/dist/src/python/components/class-declaration/class-method.js.map +1 -0
  60. package/dist/src/python/components/class-declaration/class-method.test.d.ts +2 -0
  61. package/dist/src/python/components/class-declaration/class-method.test.d.ts.map +1 -0
  62. package/dist/src/python/components/class-declaration/class-method.test.js +298 -0
  63. package/dist/src/python/components/class-declaration/class-method.test.js.map +1 -0
  64. package/dist/src/python/components/class-declaration/index.d.ts +7 -0
  65. package/dist/src/python/components/class-declaration/index.d.ts.map +1 -0
  66. package/dist/src/python/components/class-declaration/index.js +7 -0
  67. package/dist/src/python/components/class-declaration/index.js.map +1 -0
  68. package/dist/src/python/components/class-declaration/primitive-initializer.d.ts +22 -0
  69. package/dist/src/python/components/class-declaration/primitive-initializer.d.ts.map +1 -0
  70. package/dist/src/python/components/class-declaration/primitive-initializer.js +67 -0
  71. package/dist/src/python/components/class-declaration/primitive-initializer.js.map +1 -0
  72. package/dist/src/python/components/doc-element/doc-element.d.ts +46 -0
  73. package/dist/src/python/components/doc-element/doc-element.d.ts.map +1 -0
  74. package/dist/src/python/components/doc-element/doc-element.js +59 -0
  75. package/dist/src/python/components/doc-element/doc-element.js.map +1 -0
  76. package/dist/src/python/components/doc-element/index.d.ts +2 -0
  77. package/dist/src/python/components/doc-element/index.d.ts.map +1 -0
  78. package/dist/src/python/components/doc-element/index.js +2 -0
  79. package/dist/src/python/components/doc-element/index.js.map +1 -0
  80. package/dist/src/python/components/enum-declaration/enum-declaration.d.ts +8 -0
  81. package/dist/src/python/components/enum-declaration/enum-declaration.d.ts.map +1 -0
  82. package/dist/src/python/components/enum-declaration/enum-declaration.js +80 -0
  83. package/dist/src/python/components/enum-declaration/enum-declaration.js.map +1 -0
  84. package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts +2 -0
  85. package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts.map +1 -0
  86. package/dist/src/python/components/enum-declaration/enum-declaration.test.js +344 -0
  87. package/dist/src/python/components/enum-declaration/enum-declaration.test.js.map +1 -0
  88. package/dist/src/python/components/enum-declaration/enum-member.d.ts +9 -0
  89. package/dist/src/python/components/enum-declaration/enum-member.d.ts.map +1 -0
  90. package/dist/src/python/components/enum-declaration/enum-member.js +22 -0
  91. package/dist/src/python/components/enum-declaration/enum-member.js.map +1 -0
  92. package/dist/src/python/components/enum-declaration/index.d.ts +3 -0
  93. package/dist/src/python/components/enum-declaration/index.d.ts.map +1 -0
  94. package/dist/src/python/components/enum-declaration/index.js +3 -0
  95. package/dist/src/python/components/enum-declaration/index.js.map +1 -0
  96. package/dist/src/python/components/function-declaration/function-declaration.d.ts +24 -0
  97. package/dist/src/python/components/function-declaration/function-declaration.d.ts.map +1 -0
  98. package/dist/src/python/components/function-declaration/function-declaration.js +68 -0
  99. package/dist/src/python/components/function-declaration/function-declaration.js.map +1 -0
  100. package/dist/src/python/components/function-declaration/function-declaration.test.d.ts +2 -0
  101. package/dist/src/python/components/function-declaration/function-declaration.test.d.ts.map +1 -0
  102. package/dist/src/python/components/function-declaration/function-declaration.test.js +682 -0
  103. package/dist/src/python/components/function-declaration/function-declaration.test.js.map +1 -0
  104. package/dist/src/python/components/function-declaration/index.d.ts +2 -0
  105. package/dist/src/python/components/function-declaration/index.d.ts.map +1 -0
  106. package/dist/src/python/components/function-declaration/index.js +2 -0
  107. package/dist/src/python/components/function-declaration/index.js.map +1 -0
  108. package/dist/src/python/components/index.d.ts +12 -0
  109. package/dist/src/python/components/index.d.ts.map +1 -0
  110. package/dist/src/python/components/index.js +12 -0
  111. package/dist/src/python/components/index.js.map +1 -0
  112. package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts +25 -0
  113. package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts.map +1 -0
  114. package/dist/src/python/components/protocol-declaration/callable-parameters.js +33 -0
  115. package/dist/src/python/components/protocol-declaration/callable-parameters.js.map +1 -0
  116. package/dist/src/python/components/protocol-declaration/index.d.ts +3 -0
  117. package/dist/src/python/components/protocol-declaration/index.d.ts.map +1 -0
  118. package/dist/src/python/components/protocol-declaration/index.js +3 -0
  119. package/dist/src/python/components/protocol-declaration/index.js.map +1 -0
  120. package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts +8 -0
  121. package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts.map +1 -0
  122. package/dist/src/python/components/protocol-declaration/protocol-declaration.js +86 -0
  123. package/dist/src/python/components/protocol-declaration/protocol-declaration.js.map +1 -0
  124. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts +2 -0
  125. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts.map +1 -0
  126. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js +117 -0
  127. package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js.map +1 -0
  128. package/dist/src/python/components/record-expression/index.d.ts +2 -0
  129. package/dist/src/python/components/record-expression/index.d.ts.map +1 -0
  130. package/dist/src/python/components/record-expression/index.js +2 -0
  131. package/dist/src/python/components/record-expression/index.js.map +1 -0
  132. package/dist/src/python/components/record-expression/record-expression.d.ts +6 -0
  133. package/dist/src/python/components/record-expression/record-expression.d.ts.map +1 -0
  134. package/dist/src/python/components/record-expression/record-expression.js +13 -0
  135. package/dist/src/python/components/record-expression/record-expression.js.map +1 -0
  136. package/dist/src/python/components/record-expression/record-expression.test.d.ts +2 -0
  137. package/dist/src/python/components/record-expression/record-expression.test.d.ts.map +1 -0
  138. package/dist/src/python/components/record-expression/record-expression.test.js +19 -0
  139. package/dist/src/python/components/record-expression/record-expression.test.js.map +1 -0
  140. package/dist/src/python/components/type-alias-declaration/index.d.ts +2 -0
  141. package/dist/src/python/components/type-alias-declaration/index.d.ts.map +1 -0
  142. package/dist/src/python/components/type-alias-declaration/index.js +2 -0
  143. package/dist/src/python/components/type-alias-declaration/index.js.map +1 -0
  144. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts +16 -0
  145. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts.map +1 -0
  146. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js +75 -0
  147. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js.map +1 -0
  148. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts +2 -0
  149. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts.map +1 -0
  150. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js +140 -0
  151. package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js.map +1 -0
  152. package/dist/src/python/components/type-declaration/index.d.ts +2 -0
  153. package/dist/src/python/components/type-declaration/index.d.ts.map +1 -0
  154. package/dist/src/python/components/type-declaration/index.js +2 -0
  155. package/dist/src/python/components/type-declaration/index.js.map +1 -0
  156. package/dist/src/python/components/type-declaration/type-declaration.d.ts +11 -0
  157. package/dist/src/python/components/type-declaration/type-declaration.d.ts.map +1 -0
  158. package/dist/src/python/components/type-declaration/type-declaration.js +31 -0
  159. package/dist/src/python/components/type-declaration/type-declaration.js.map +1 -0
  160. package/dist/src/python/components/type-declaration/type-declaration.test.d.ts +2 -0
  161. package/dist/src/python/components/type-declaration/type-declaration.test.d.ts.map +1 -0
  162. package/dist/src/python/components/type-declaration/type-declaration.test.js +69 -0
  163. package/dist/src/python/components/type-declaration/type-declaration.test.js.map +1 -0
  164. package/dist/src/python/components/type-expression/index.d.ts +2 -0
  165. package/dist/src/python/components/type-expression/index.d.ts.map +1 -0
  166. package/dist/src/python/components/type-expression/index.js +2 -0
  167. package/dist/src/python/components/type-expression/index.js.map +1 -0
  168. package/dist/src/python/components/type-expression/type-expression.d.ts +12 -0
  169. package/dist/src/python/components/type-expression/type-expression.d.ts.map +1 -0
  170. package/dist/src/python/components/type-expression/type-expression.js +348 -0
  171. package/dist/src/python/components/type-expression/type-expression.js.map +1 -0
  172. package/dist/src/python/components/type-expression/type-expression.test.d.ts +2 -0
  173. package/dist/src/python/components/type-expression/type-expression.test.d.ts.map +1 -0
  174. package/dist/src/python/components/type-expression/type-expression.test.js +503 -0
  175. package/dist/src/python/components/type-expression/type-expression.test.js.map +1 -0
  176. package/dist/src/python/index.d.ts +4 -0
  177. package/dist/src/python/index.d.ts.map +1 -0
  178. package/dist/src/python/index.js +4 -0
  179. package/dist/src/python/index.js.map +1 -0
  180. package/dist/src/python/lib.d.ts +68 -0
  181. package/dist/src/python/lib.d.ts.map +1 -0
  182. package/dist/src/python/lib.js +38 -0
  183. package/dist/src/python/lib.js.map +1 -0
  184. package/dist/src/python/test-utils.d.ts +8 -0
  185. package/dist/src/python/test-utils.d.ts.map +1 -0
  186. package/dist/src/python/test-utils.js +25 -0
  187. package/dist/src/python/test-utils.js.map +1 -0
  188. package/dist/src/python/utils/index.d.ts +4 -0
  189. package/dist/src/python/utils/index.d.ts.map +1 -0
  190. package/dist/src/python/utils/index.js +4 -0
  191. package/dist/src/python/utils/index.js.map +1 -0
  192. package/dist/src/python/utils/operation.d.ts +27 -0
  193. package/dist/src/python/utils/operation.d.ts.map +1 -0
  194. package/dist/src/python/utils/operation.js +139 -0
  195. package/dist/src/python/utils/operation.js.map +1 -0
  196. package/dist/src/python/utils/refkey.d.ts +23 -0
  197. package/dist/src/python/utils/refkey.d.ts.map +1 -0
  198. package/dist/src/python/utils/refkey.js +36 -0
  199. package/dist/src/python/utils/refkey.js.map +1 -0
  200. package/dist/src/python/utils/type.d.ts +19 -0
  201. package/dist/src/python/utils/type.d.ts.map +1 -0
  202. package/dist/src/python/utils/type.js +24 -0
  203. package/dist/src/python/utils/type.js.map +1 -0
  204. package/dist/src/typescript/components/function-declaration.d.ts.map +1 -1
  205. package/dist/src/typescript/components/function-declaration.js.map +1 -1
  206. package/package.json +12 -4
  207. package/package.json.bak +13 -4
  208. package/src/core/components/overrides/component-overrides.tsx +9 -6
  209. package/src/python/builtins.ts +43 -0
  210. package/src/python/components/array-expression/array-expression.test.tsx +14 -0
  211. package/src/python/components/array-expression/array-expression.tsx +11 -0
  212. package/src/python/components/array-expression/index.ts +1 -0
  213. package/src/python/components/atom/atom.test.tsx +244 -0
  214. package/src/python/components/atom/atom.tsx +95 -0
  215. package/src/python/components/atom/index.ts +1 -0
  216. package/src/python/components/class-declaration/class-bases.tsx +92 -0
  217. package/src/python/components/class-declaration/class-body.tsx +56 -0
  218. package/src/python/components/class-declaration/class-declaration.test.tsx +1414 -0
  219. package/src/python/components/class-declaration/class-declaration.tsx +116 -0
  220. package/src/python/components/class-declaration/class-member.test.tsx +194 -0
  221. package/src/python/components/class-declaration/class-member.tsx +67 -0
  222. package/src/python/components/class-declaration/class-method.test.tsx +250 -0
  223. package/src/python/components/class-declaration/class-method.tsx +97 -0
  224. package/src/python/components/class-declaration/index.ts +6 -0
  225. package/src/python/components/class-declaration/primitive-initializer.tsx +62 -0
  226. package/src/python/components/doc-element/doc-element.tsx +83 -0
  227. package/src/python/components/doc-element/index.ts +1 -0
  228. package/src/python/components/enum-declaration/enum-declaration.test.tsx +319 -0
  229. package/src/python/components/enum-declaration/enum-declaration.tsx +77 -0
  230. package/src/python/components/enum-declaration/enum-member.tsx +21 -0
  231. package/src/python/components/enum-declaration/index.ts +2 -0
  232. package/src/python/components/function-declaration/function-declaration.test.tsx +582 -0
  233. package/src/python/components/function-declaration/function-declaration.tsx +90 -0
  234. package/src/python/components/function-declaration/index.ts +1 -0
  235. package/src/python/components/index.ts +11 -0
  236. package/src/python/components/protocol-declaration/callable-parameters.tsx +44 -0
  237. package/src/python/components/protocol-declaration/index.ts +2 -0
  238. package/src/python/components/protocol-declaration/protocol-declaration.test.tsx +106 -0
  239. package/src/python/components/protocol-declaration/protocol-declaration.tsx +73 -0
  240. package/src/python/components/record-expression/index.ts +1 -0
  241. package/src/python/components/record-expression/record-expression.test.tsx +14 -0
  242. package/src/python/components/record-expression/record-expression.tsx +13 -0
  243. package/src/python/components/type-alias-declaration/index.ts +1 -0
  244. package/src/python/components/type-alias-declaration/type-alias-declaration.test.tsx +117 -0
  245. package/src/python/components/type-alias-declaration/type-alias-declaration.tsx +67 -0
  246. package/src/python/components/type-declaration/index.ts +1 -0
  247. package/src/python/components/type-declaration/type-declaration.test.tsx +58 -0
  248. package/src/python/components/type-declaration/type-declaration.tsx +26 -0
  249. package/src/python/components/type-expression/index.ts +1 -0
  250. package/src/python/components/type-expression/type-expression.test.tsx +463 -0
  251. package/src/python/components/type-expression/type-expression.tsx +333 -0
  252. package/src/python/index.ts +3 -0
  253. package/src/python/lib.ts +40 -0
  254. package/src/python/test-utils.tsx +31 -0
  255. package/src/python/utils/index.ts +3 -0
  256. package/src/python/utils/operation.ts +161 -0
  257. package/src/python/utils/refkey.ts +36 -0
  258. package/src/python/utils/type.ts +31 -0
  259. package/src/typescript/components/function-declaration.tsx +4 -2
@@ -0,0 +1,244 @@
1
+ import { getOutput } from "#python/test-utils.js";
2
+ import { Tester } from "#test/test-host.js";
3
+ import { type Model, type Program, type Value } from "@typespec/compiler";
4
+ import { t } from "@typespec/compiler/testing";
5
+ import { $ } from "@typespec/compiler/typekit";
6
+ import { assert, beforeAll, describe, expect, it } from "vitest";
7
+ import { Atom } from "../../index.js";
8
+
9
+ let program: Program;
10
+
11
+ beforeAll(async () => {
12
+ const result = await Tester.compile("");
13
+ program = result.program;
14
+ });
15
+
16
+ describe("NullValue", () => {
17
+ it("null value", async () => {
18
+ const value = { entityKind: "Value", valueKind: "NullValue", value: null } as Value;
19
+
20
+ await testValueExpression(value, `None`);
21
+ });
22
+ });
23
+
24
+ describe("StringValue", () => {
25
+ it("normal string", async () => {
26
+ const value = $(program).value.createString("test");
27
+
28
+ await testValueExpression(value, `"test"`);
29
+ });
30
+
31
+ it("empty string", async () => {
32
+ const value = $(program).value.createString("");
33
+
34
+ await testValueExpression(value, `""`);
35
+ });
36
+ });
37
+
38
+ describe("BooleanValue", () => {
39
+ it("True", async () => {
40
+ const value = $(program).value.createBoolean(true);
41
+
42
+ await testValueExpression(value, `True`);
43
+ });
44
+
45
+ it("False", async () => {
46
+ const value = $(program).value.createBoolean(false);
47
+
48
+ await testValueExpression(value, `False`);
49
+ });
50
+ });
51
+
52
+ describe("NumericValue", () => {
53
+ it("integers", async () => {
54
+ const value = $(program).value.createNumeric(42);
55
+
56
+ await testValueExpression(value, `42`);
57
+ });
58
+
59
+ it("decimals", async () => {
60
+ const fractional = $(program).value.createNumeric(42.5);
61
+ await testValueExpression(fractional, `42.5`);
62
+ });
63
+
64
+ it("decimals with .0", async () => {
65
+ // Generic Atom (no hint) normalizes 42.0 to 42 because it uses asNumber()
66
+ const value = $(program).value.createNumeric(42.0);
67
+ await testValueExpression(value, `42`);
68
+ });
69
+
70
+ it("decimals with .0 when float", async () => {
71
+ const value = $(program).value.createNumeric(42.0);
72
+ expect(getOutput(program, [<Atom value={value} float />])).toRenderTo(`42.0`);
73
+ });
74
+
75
+ it("negative integers", async () => {
76
+ const value = $(program).value.createNumeric(-42);
77
+ await testValueExpression(value, `-42`);
78
+ });
79
+
80
+ it("negative decimals", async () => {
81
+ const value = $(program).value.createNumeric(-42.5);
82
+ await testValueExpression(value, `-42.5`);
83
+ });
84
+
85
+ it("zero", async () => {
86
+ const value = $(program).value.createNumeric(0);
87
+ await testValueExpression(value, `0`);
88
+ });
89
+
90
+ it("zero with float", async () => {
91
+ const value = $(program).value.createNumeric(0);
92
+ expect(getOutput(program, [<Atom value={value} float />])).toRenderTo(`0.0`);
93
+ });
94
+
95
+ it("exponent that resolves to integer", async () => {
96
+ const value = $(program).value.createNumeric(1e3);
97
+ await testValueExpression(value, `1000`);
98
+ });
99
+
100
+ it("exponent that resolves to integer with float", async () => {
101
+ const value = $(program).value.createNumeric(1e3);
102
+ expect(getOutput(program, [<Atom value={value} float />])).toRenderTo(`1000.0`);
103
+ });
104
+
105
+ it("small decimal via exponent", async () => {
106
+ const value = $(program).value.createNumeric(1e-3);
107
+ await testValueExpression(value, `0.001`);
108
+ });
109
+ });
110
+
111
+ describe("ArrayValue", () => {
112
+ it("empty", async () => {
113
+ // Can be replaced with TypeKit once #6976 is implemented
114
+ const value = {
115
+ entityKind: "Value",
116
+ valueKind: "ArrayValue",
117
+ values: [],
118
+ } as unknown as Value;
119
+ await testValueExpression(value, `[]`);
120
+ });
121
+
122
+ it("with mixed values", async () => {
123
+ // Can be replaced with TypeKit once #6976 is implemented
124
+ const value = {
125
+ entityKind: "Value",
126
+ valueKind: "ArrayValue",
127
+ values: [
128
+ $(program).value.createString("some_text"),
129
+ $(program).value.createNumeric(42),
130
+ $(program).value.createBoolean(true),
131
+ {
132
+ entityKind: "Value",
133
+ valueKind: "ArrayValue",
134
+ values: [
135
+ $(program).value.createNumeric(1),
136
+ $(program).value.createNumeric(2),
137
+ $(program).value.createNumeric(3),
138
+ ],
139
+ } as Value,
140
+ ],
141
+ } as Value;
142
+ await testValueExpression(value, `["some_text", 42, True, [1, 2, 3]]`);
143
+ });
144
+ });
145
+
146
+ describe("ScalarValue", () => {
147
+ it("utcDateTime.fromISO correctly supplied", async () => {
148
+ const { minDate } = await Tester.compile(t.code`
149
+ model ${t.model("DateRange")} {
150
+ @encode("rfc7231")
151
+ ${t.modelProperty("minDate")}: ${t.type("utcDateTime")} = utcDateTime.fromISO("2024-02-15T18:36:03Z");
152
+ }
153
+ `);
154
+ await testValueExpression(
155
+ minDate.defaultValue!,
156
+ `from datetime import datetime
157
+ from datetime import timezone
158
+
159
+
160
+ datetime(2024, 2, 15, 18, 36, 3, tzinfo=timezone.utc)`,
161
+ );
162
+ });
163
+
164
+ it("Unsupported scalar constructor", async () => {
165
+ const { IpAddress } = await Tester.compile(t.code`
166
+ scalar ${t.scalar("ipv4")} extends ${t.scalar("string")} {
167
+ init fromInt(value: uint32);
168
+ }
169
+
170
+ @example (#{ip: ipv4.fromInt(2130706433)})
171
+ model ${t.model("IpAddress")} {
172
+ ${t.modelProperty("ip")}: ${t.type("ipv4")};
173
+ }
174
+ `);
175
+
176
+ const value = getExampleValue(IpAddress);
177
+ await expect(testValueExpression(value, ``)).rejects.toThrow(
178
+ /Unsupported scalar constructor fromInt/,
179
+ );
180
+ });
181
+ });
182
+
183
+ describe("ObjectValue", () => {
184
+ it("empty object", async () => {
185
+ // Can be replaced with TypeKit once #6976 is implemented
186
+ const { ObjectValue } = await Tester.compile(t.code`
187
+ @example(#{})
188
+ model ${t.model("ObjectValue")} {};
189
+ `);
190
+
191
+ const value = getExampleValue(ObjectValue);
192
+ await testValueExpression(value, `{}`);
193
+ });
194
+
195
+ it("object with properties", async () => {
196
+ // Can be replaced with TypeKit once #6976 is implemented
197
+ const { ObjectValue } = await Tester.compile(t.code`
198
+ @example(#{aNumber: 5, aString: "foo", aBoolean: true})
199
+ model ${t.model("ObjectValue")} {
200
+ ${t.modelProperty("aNumber")}: int32;
201
+ ${t.modelProperty("aString")}: string;
202
+ ${t.modelProperty("aBoolean")}: boolean;
203
+ };
204
+ `);
205
+ const value = getExampleValue(ObjectValue);
206
+ await testValueExpression(value, `{"aNumber": 5, "aString": "foo", "aBoolean": True}`);
207
+ });
208
+ });
209
+
210
+ describe("EnumValue", () => {
211
+ it("different EnumValue types", async () => {
212
+ // Can be replaced with TypeKit once #6976 is implemented
213
+ const { Red, Green, Blue } = await Tester.compile(t.code`
214
+ enum ${t.enum("Color")} {
215
+ Red,
216
+ Green: 3,
217
+ Blue: "cyan",
218
+ }
219
+ const ${t.value("Red")} = ${t.enumValue("Color.Red")};
220
+ const ${t.value("Green")} = ${t.enumValue("Color.Green")};
221
+ const ${t.value("Blue")} = ${t.enumValue("Color.Blue")};
222
+ `);
223
+
224
+ await testValueExpression(Red, `"Red"`);
225
+ await testValueExpression(Green, `3`);
226
+ await testValueExpression(Blue, `"cyan"`);
227
+ });
228
+ });
229
+
230
+ /**
231
+ * Helper that renders a value expression and checks the output against the expected value.
232
+ */
233
+ async function testValueExpression(value: Value, expected: string) {
234
+ expect(getOutput(program, [<Atom value={value} />])).toRenderTo(`${expected}`);
235
+ }
236
+
237
+ /**
238
+ * Extracts the value marked with the @example decorator from a model.
239
+ */
240
+ function getExampleValue(model: Model): Value {
241
+ const decorator = model?.decorators.find((d) => d.definition?.name === "@example");
242
+ assert.exists(decorator?.args[0]?.value, "unable to find example decorator");
243
+ return decorator.args[0].value as Value;
244
+ }
@@ -0,0 +1,95 @@
1
+ import { type Children } from "@alloy-js/core";
2
+ import * as py from "@alloy-js/python";
3
+ import { compilerAssert, type Value } from "@typespec/compiler";
4
+ import { datetimeModule } from "../../builtins.js";
5
+
6
+ /**
7
+ * Base properties for the {@link Atom} component.
8
+ */
9
+ interface BaseAtomProps {
10
+ /**
11
+ * The TypeSpec value to be converted to a Python expression.
12
+ */
13
+ value: Value;
14
+ }
15
+
16
+ /**
17
+ * Properties for the {@link Atom} component when dealing with numeric values.
18
+ */
19
+ interface NumericAtomProps extends BaseAtomProps {
20
+ /**
21
+ * Hint that this numeric value should be emitted as a float (e.g., 42 -> 42.0).
22
+ * Only affects NumericValue.
23
+ */
24
+ float?: boolean;
25
+ }
26
+
27
+ /**
28
+ * All possible properties for the {@link Atom} component.
29
+ */
30
+ type AtomProps = BaseAtomProps | NumericAtomProps;
31
+
32
+ /**
33
+ * Generates a Python atom from a TypeSpec value.
34
+ * @param props properties for the atom
35
+ * @returns {@link Children} representing the Python value expression
36
+ */
37
+ export function Atom(props: Readonly<AtomProps>): Children {
38
+ switch (props.value.valueKind) {
39
+ case "StringValue":
40
+ case "BooleanValue":
41
+ case "NullValue":
42
+ return <py.Atom jsValue={props.value.value} />;
43
+ case "NumericValue": {
44
+ const num = props.value.value.asNumber();
45
+ const isNonInteger = num != null && !Number.isInteger(num);
46
+ const numericProps = props as NumericAtomProps;
47
+ const asFloat = isNonInteger || numericProps.float;
48
+ return <py.Atom jsValue={num} asFloat={asFloat} />;
49
+ }
50
+ case "ArrayValue":
51
+ return (
52
+ <py.Atom
53
+ jsValue={props.value.values.map((v) => (
54
+ <Atom value={v} />
55
+ ))}
56
+ />
57
+ );
58
+ case "ScalarValue":
59
+ compilerAssert(
60
+ props.value.value.name === "fromISO",
61
+ `Unsupported scalar constructor ${props.value.value.name}`,
62
+ props.value,
63
+ );
64
+ return handleISOStringValue(props.value);
65
+ case "ObjectValue":
66
+ const jsProperties: Record<string, Children> = {};
67
+ for (const [key, value] of props.value.properties) {
68
+ jsProperties[key] = Atom({ value: value.value });
69
+ }
70
+ return <py.Atom jsValue={jsProperties} />;
71
+ case "EnumValue":
72
+ return <py.Atom jsValue={props.value.value.value ?? props.value.value.name} />;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Handles the conversion of ISO date strings to Python datetime objects.
78
+ * @param value the TypeSpec value containing the ISO string
79
+ * @returns {@link Children} representing the Python datetime expression
80
+ */
81
+ function handleISOStringValue(value: Value & { valueKind: "ScalarValue" }): Children {
82
+ const arg0 = value.value.args[0];
83
+ if (arg0.valueKind !== "StringValue") {
84
+ throw new Error("Expected arg0 to be a StringValue");
85
+ }
86
+ const isoString = arg0.value;
87
+ const date = new Date(isoString);
88
+ return (
89
+ <>
90
+ {datetimeModule["."]["datetime"]}({date.getUTCFullYear()}, {date.getUTCMonth() + 1},{" "}
91
+ {date.getUTCDate()}, {date.getUTCHours()}, {date.getUTCMinutes()}, {date.getUTCSeconds()},
92
+ tzinfo={datetimeModule["."]["timezone"]}.utc)
93
+ </>
94
+ );
95
+ }
@@ -0,0 +1 @@
1
+ export * from "./atom.js";
@@ -0,0 +1,92 @@
1
+ import { abcModule } from "#python/builtins.js";
2
+ import { type Children } from "@alloy-js/core";
3
+ import * as py from "@alloy-js/python";
4
+ import { isTemplateDeclarationOrInstance, type Interface, type Model } from "@typespec/compiler";
5
+ import { useTsp } from "../../../core/context/tsp-context.js";
6
+ import { efRefkey } from "../../utils/refkey.js";
7
+ import { TypeExpression } from "../type-expression/type-expression.js";
8
+
9
+ export interface ClassBasesProps {
10
+ /**
11
+ * The TypeSpec type to derive bases from. If not provided, only explicit bases are used.
12
+ */
13
+ type?: Model | Interface;
14
+
15
+ /**
16
+ * Explicit base classes to include.
17
+ */
18
+ bases?: Children[];
19
+
20
+ /**
21
+ * Whether the class is abstract. If true, ABC is added to the bases.
22
+ */
23
+ abstract?: boolean;
24
+
25
+ /**
26
+ * Additional bases to include (e.g., for future Generic[T] support).
27
+ */
28
+ extraBases?: Children[];
29
+ }
30
+
31
+ /**
32
+ * Computes the base classes for a Python class declaration.
33
+ *
34
+ * Combines:
35
+ * - Explicit bases from props
36
+ * - Type-derived bases (from TypeSpec model inheritance):
37
+ * - Template instances (e.g., `Response<string>` → `Response[str]`)
38
+ * - Regular models (e.g., `BaseWidget`) via py.Reference
39
+ * - Arrays via TypeExpression for `typing.Sequence[T]` rendering
40
+ * - Records are not supported and ignored
41
+ * - Extra bases (for future generics support)
42
+ * - ABC if abstract (always last for proper Python MRO)
43
+ *
44
+ * For interfaces, type-derived bases are empty because TypeSpec flattens interface inheritance.
45
+ *
46
+ * @returns Array of base class Children, or empty array if none.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * const bases = ClassBases({ type: model, abstract: true });
51
+ * <py.ClassDeclaration bases={bases.length ? bases : undefined} />
52
+ * ```
53
+ */
54
+ export function ClassBases(props: ClassBasesProps): Children[] {
55
+ const { $ } = useTsp();
56
+ const extraBases = [...(props.extraBases ?? [])];
57
+
58
+ // Add extends/inheritance from the TypeSpec type if present
59
+ if (props.type && $.model.is(props.type)) {
60
+ const type = props.type;
61
+
62
+ if (type.baseModel) {
63
+ if ($.array.is(type.baseModel)) {
64
+ extraBases.push(<TypeExpression type={type.baseModel} />);
65
+ } else if ($.record.is(type.baseModel)) {
66
+ // Record-based scenarios are not supported, do nothing here
67
+ } else if (isTemplateDeclarationOrInstance(type.baseModel)) {
68
+ // Template type (declaration or instance) - needs TypeExpression for type parameter handling
69
+ extraBases.push(<TypeExpression type={type.baseModel} />);
70
+ } else {
71
+ // Regular model - use py.Reference for proper symbol resolution
72
+ extraBases.push(<py.Reference refkey={efRefkey(type.baseModel)} />);
73
+ }
74
+ }
75
+
76
+ // Handle index types: Arrays (int indexes) are supported, Records are not
77
+ const indexType = $.model.getIndexType(type);
78
+ if (indexType && !$.record.is(indexType)) {
79
+ extraBases.push(<TypeExpression type={indexType} />);
80
+ }
81
+ }
82
+
83
+ // Combine explicit bases from props with extraBases (Generic, extends, etc.)
84
+ const allBases = (props.bases ?? []).concat(extraBases);
85
+
86
+ // For abstract classes, always include ABC (last for proper MRO)
87
+ if (props.abstract) {
88
+ return [...allBases, abcModule["."]["ABC"]];
89
+ }
90
+
91
+ return allBases;
92
+ }
@@ -0,0 +1,56 @@
1
+ import { For, type Children } from "@alloy-js/core";
2
+ import { type Interface, type Model, type ModelProperty, type Operation } from "@typespec/compiler";
3
+ import type { Typekit } from "@typespec/compiler/typekit";
4
+ import { createRekeyableMap } from "@typespec/compiler/utils";
5
+ import { useTsp } from "../../../core/context/tsp-context.js";
6
+ import { ClassMember } from "./class-member.js";
7
+
8
+ export interface ClassBodyProps {
9
+ type: Model | Interface;
10
+ abstract?: boolean;
11
+ methodType?: "method" | "class" | "static";
12
+ children?: Children;
13
+ }
14
+
15
+ /**
16
+ * Gets type members (properties or operations) from a Model or Interface.
17
+ */
18
+ function getTypeMembers($: Typekit, type: Model | Interface): (ModelProperty | Operation)[] {
19
+ if ($.model.is(type)) {
20
+ return Array.from($.model.getProperties(type).values());
21
+ } else if (type.kind === "Interface") {
22
+ return Array.from(createRekeyableMap(type.operations).values());
23
+ } else {
24
+ throw new Error("Expected Model or Interface type");
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Renders the body of a class declaration.
30
+ * For models, renders properties as dataclass fields.
31
+ * For interfaces, renders operations as abstract methods.
32
+ * Includes any additional children provided.
33
+ */
34
+ export function ClassBody(props: ClassBodyProps): Children {
35
+ const { $ } = useTsp();
36
+ const typeMembers = getTypeMembers($, props.type);
37
+
38
+ // Throw error for models with additional properties (Record-based scenarios)
39
+ if ($.model.is(props.type)) {
40
+ const additionalPropsRecord = $.model.getAdditionalPropertiesRecord(props.type);
41
+ if (additionalPropsRecord) {
42
+ throw new Error("Models with additional properties (Record[…]) are not supported");
43
+ }
44
+ }
45
+
46
+ return (
47
+ <>
48
+ <For each={typeMembers} line>
49
+ {(typeMember) => (
50
+ <ClassMember type={typeMember} abstract={props.abstract} methodType={props.methodType} />
51
+ )}
52
+ </For>
53
+ {props.children}
54
+ </>
55
+ );
56
+ }