@alloy-js/python 0.0.1

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 (206) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/LICENSE +7 -0
  3. package/api-extractor.json +4 -0
  4. package/dist/src/builtins/python.d.ts +9 -0
  5. package/dist/src/builtins/python.d.ts.map +1 -0
  6. package/dist/src/builtins/python.js +17 -0
  7. package/dist/src/components/Atom.d.ts +19 -0
  8. package/dist/src/components/Atom.d.ts.map +1 -0
  9. package/dist/src/components/Atom.js +82 -0
  10. package/dist/src/components/CallSignature.d.ts +79 -0
  11. package/dist/src/components/CallSignature.d.ts.map +1 -0
  12. package/dist/src/components/CallSignature.js +201 -0
  13. package/dist/src/components/ClassDeclaration.d.ts +37 -0
  14. package/dist/src/components/ClassDeclaration.d.ts.map +1 -0
  15. package/dist/src/components/ClassDeclaration.js +83 -0
  16. package/dist/src/components/ClassInstantiation.d.ts +24 -0
  17. package/dist/src/components/ClassInstantiation.d.ts.map +1 -0
  18. package/dist/src/components/ClassInstantiation.js +35 -0
  19. package/dist/src/components/Declaration.d.ts +48 -0
  20. package/dist/src/components/Declaration.d.ts.map +1 -0
  21. package/dist/src/components/Declaration.js +37 -0
  22. package/dist/src/components/EnumDeclaration.d.ts +164 -0
  23. package/dist/src/components/EnumDeclaration.d.ts.map +1 -0
  24. package/dist/src/components/EnumDeclaration.js +278 -0
  25. package/dist/src/components/EnumMember.d.ts +46 -0
  26. package/dist/src/components/EnumMember.d.ts.map +1 -0
  27. package/dist/src/components/EnumMember.js +67 -0
  28. package/dist/src/components/FunctionCallExpression.d.ts +19 -0
  29. package/dist/src/components/FunctionCallExpression.d.ts.map +1 -0
  30. package/dist/src/components/FunctionCallExpression.js +40 -0
  31. package/dist/src/components/FunctionDeclaration.d.ts +47 -0
  32. package/dist/src/components/FunctionDeclaration.d.ts.map +1 -0
  33. package/dist/src/components/FunctionDeclaration.js +107 -0
  34. package/dist/src/components/ImportStatement.d.ts +39 -0
  35. package/dist/src/components/ImportStatement.d.ts.map +1 -0
  36. package/dist/src/components/ImportStatement.js +104 -0
  37. package/dist/src/components/MemberExpression.d.ts +97 -0
  38. package/dist/src/components/MemberExpression.d.ts.map +1 -0
  39. package/dist/src/components/MemberExpression.js +308 -0
  40. package/dist/src/components/NoNamePolicy.d.ts +23 -0
  41. package/dist/src/components/NoNamePolicy.d.ts.map +1 -0
  42. package/dist/src/components/NoNamePolicy.js +27 -0
  43. package/dist/src/components/PyDoc.d.ts +90 -0
  44. package/dist/src/components/PyDoc.d.ts.map +1 -0
  45. package/dist/src/components/PyDoc.js +280 -0
  46. package/dist/src/components/PythonBlock.d.ts +23 -0
  47. package/dist/src/components/PythonBlock.d.ts.map +1 -0
  48. package/dist/src/components/PythonBlock.js +31 -0
  49. package/dist/src/components/Reference.d.ts +13 -0
  50. package/dist/src/components/Reference.d.ts.map +1 -0
  51. package/dist/src/components/Reference.js +18 -0
  52. package/dist/src/components/SourceFile.d.ts +46 -0
  53. package/dist/src/components/SourceFile.d.ts.map +1 -0
  54. package/dist/src/components/SourceFile.js +75 -0
  55. package/dist/src/components/StatementList.d.ts +25 -0
  56. package/dist/src/components/StatementList.d.ts.map +1 -0
  57. package/dist/src/components/StatementList.js +29 -0
  58. package/dist/src/components/VariableDeclaration.d.ts +62 -0
  59. package/dist/src/components/VariableDeclaration.d.ts.map +1 -0
  60. package/dist/src/components/VariableDeclaration.js +131 -0
  61. package/dist/src/components/index.d.ts +19 -0
  62. package/dist/src/components/index.d.ts.map +1 -0
  63. package/dist/src/components/index.js +18 -0
  64. package/dist/src/create-module.d.ts +16 -0
  65. package/dist/src/create-module.d.ts.map +1 -0
  66. package/dist/src/create-module.js +64 -0
  67. package/dist/src/index.d.ts +8 -0
  68. package/dist/src/index.d.ts.map +1 -0
  69. package/dist/src/index.js +7 -0
  70. package/dist/src/name-policy.d.ts +5 -0
  71. package/dist/src/name-policy.d.ts.map +1 -0
  72. package/dist/src/name-policy.js +47 -0
  73. package/dist/src/parameter-descriptor.d.ts +31 -0
  74. package/dist/src/parameter-descriptor.d.ts.map +1 -0
  75. package/dist/src/parameter-descriptor.js +1 -0
  76. package/dist/src/symbol-creation.d.ts +4 -0
  77. package/dist/src/symbol-creation.d.ts.map +1 -0
  78. package/dist/src/symbol-creation.js +24 -0
  79. package/dist/src/symbols/custom-output-scope.d.ts +10 -0
  80. package/dist/src/symbols/custom-output-scope.d.ts.map +1 -0
  81. package/dist/src/symbols/custom-output-scope.js +25 -0
  82. package/dist/src/symbols/index.d.ts +7 -0
  83. package/dist/src/symbols/index.d.ts.map +1 -0
  84. package/dist/src/symbols/index.js +6 -0
  85. package/dist/src/symbols/python-member-scope.d.ts +7 -0
  86. package/dist/src/symbols/python-member-scope.d.ts.map +1 -0
  87. package/dist/src/symbols/python-member-scope.js +9 -0
  88. package/dist/src/symbols/python-module-scope.d.ts +25 -0
  89. package/dist/src/symbols/python-module-scope.d.ts.map +1 -0
  90. package/dist/src/symbols/python-module-scope.js +52 -0
  91. package/dist/src/symbols/python-output-symbol.d.ts +19 -0
  92. package/dist/src/symbols/python-output-symbol.d.ts.map +1 -0
  93. package/dist/src/symbols/python-output-symbol.js +22 -0
  94. package/dist/src/symbols/reference.d.ts +4 -0
  95. package/dist/src/symbols/reference.d.ts.map +1 -0
  96. package/dist/src/symbols/reference.js +60 -0
  97. package/dist/src/symbols/scopes.d.ts +5 -0
  98. package/dist/src/symbols/scopes.d.ts.map +1 -0
  99. package/dist/src/symbols/scopes.js +4 -0
  100. package/dist/src/utils.d.ts +7 -0
  101. package/dist/src/utils.d.ts.map +1 -0
  102. package/dist/src/utils.js +12 -0
  103. package/dist/test/callsignatures.test.d.ts +2 -0
  104. package/dist/test/callsignatures.test.d.ts.map +1 -0
  105. package/dist/test/callsignatures.test.js +276 -0
  106. package/dist/test/classdeclarations.test.d.ts +2 -0
  107. package/dist/test/classdeclarations.test.d.ts.map +1 -0
  108. package/dist/test/classdeclarations.test.js +397 -0
  109. package/dist/test/classinstantiations.test.d.ts +2 -0
  110. package/dist/test/classinstantiations.test.d.ts.map +1 -0
  111. package/dist/test/classinstantiations.test.js +168 -0
  112. package/dist/test/enums.test.d.ts +2 -0
  113. package/dist/test/enums.test.d.ts.map +1 -0
  114. package/dist/test/enums.test.js +211 -0
  115. package/dist/test/externals.test.d.ts +2 -0
  116. package/dist/test/externals.test.d.ts.map +1 -0
  117. package/dist/test/externals.test.js +219 -0
  118. package/dist/test/functioncallexpressions.test.d.ts +2 -0
  119. package/dist/test/functioncallexpressions.test.d.ts.map +1 -0
  120. package/dist/test/functioncallexpressions.test.js +156 -0
  121. package/dist/test/functiondeclaration.test.d.ts +2 -0
  122. package/dist/test/functiondeclaration.test.d.ts.map +1 -0
  123. package/dist/test/functiondeclaration.test.js +363 -0
  124. package/dist/test/imports.test.d.ts +2 -0
  125. package/dist/test/imports.test.d.ts.map +1 -0
  126. package/dist/test/imports.test.js +262 -0
  127. package/dist/test/memberexpressions.test.d.ts +2 -0
  128. package/dist/test/memberexpressions.test.d.ts.map +1 -0
  129. package/dist/test/memberexpressions.test.js +879 -0
  130. package/dist/test/namepolicies.test.d.ts +2 -0
  131. package/dist/test/namepolicies.test.d.ts.map +1 -0
  132. package/dist/test/namepolicies.test.js +109 -0
  133. package/dist/test/pydocs.test.d.ts +2 -0
  134. package/dist/test/pydocs.test.d.ts.map +1 -0
  135. package/dist/test/pydocs.test.js +500 -0
  136. package/dist/test/references.test.d.ts +2 -0
  137. package/dist/test/references.test.d.ts.map +1 -0
  138. package/dist/test/references.test.js +49 -0
  139. package/dist/test/sourcefiles.test.d.ts +2 -0
  140. package/dist/test/sourcefiles.test.d.ts.map +1 -0
  141. package/dist/test/sourcefiles.test.js +198 -0
  142. package/dist/test/utils.d.ts +23 -0
  143. package/dist/test/utils.d.ts.map +1 -0
  144. package/dist/test/utils.js +88 -0
  145. package/dist/test/values.test.d.ts +2 -0
  146. package/dist/test/values.test.d.ts.map +1 -0
  147. package/dist/test/values.test.js +78 -0
  148. package/dist/test/variables.test.d.ts +2 -0
  149. package/dist/test/variables.test.d.ts.map +1 -0
  150. package/dist/test/variables.test.js +173 -0
  151. package/dist/tsconfig.tsbuildinfo +1 -0
  152. package/package.json +39 -0
  153. package/src/builtins/python.ts +20 -0
  154. package/src/components/Atom.tsx +76 -0
  155. package/src/components/CallSignature.tsx +251 -0
  156. package/src/components/ClassDeclaration.tsx +98 -0
  157. package/src/components/ClassInstantiation.tsx +54 -0
  158. package/src/components/Declaration.tsx +91 -0
  159. package/src/components/EnumDeclaration.tsx +291 -0
  160. package/src/components/EnumMember.tsx +92 -0
  161. package/src/components/FunctionCallExpression.tsx +36 -0
  162. package/src/components/FunctionDeclaration.tsx +121 -0
  163. package/src/components/ImportStatement.tsx +134 -0
  164. package/src/components/MemberExpression.tsx +456 -0
  165. package/src/components/NoNamePolicy.tsx +31 -0
  166. package/src/components/PyDoc.tsx +331 -0
  167. package/src/components/PythonBlock.tsx +26 -0
  168. package/src/components/Reference.tsx +21 -0
  169. package/src/components/SourceFile.tsx +93 -0
  170. package/src/components/StatementList.tsx +28 -0
  171. package/src/components/VariableDeclaration.tsx +180 -0
  172. package/src/components/index.ts +18 -0
  173. package/src/create-module.ts +102 -0
  174. package/src/index.ts +7 -0
  175. package/src/name-policy.ts +101 -0
  176. package/src/parameter-descriptor.ts +36 -0
  177. package/src/symbol-creation.ts +36 -0
  178. package/src/symbols/custom-output-scope.ts +35 -0
  179. package/src/symbols/index.ts +6 -0
  180. package/src/symbols/python-member-scope.ts +12 -0
  181. package/src/symbols/python-module-scope.ts +89 -0
  182. package/src/symbols/python-output-symbol.ts +36 -0
  183. package/src/symbols/reference.ts +99 -0
  184. package/src/symbols/scopes.ts +9 -0
  185. package/src/utils.ts +27 -0
  186. package/temp/api.json +7207 -0
  187. package/test/callsignatures.test.tsx +256 -0
  188. package/test/classdeclarations.test.tsx +320 -0
  189. package/test/classinstantiations.test.tsx +159 -0
  190. package/test/enums.test.tsx +203 -0
  191. package/test/externals.test.tsx +190 -0
  192. package/test/functioncallexpressions.test.tsx +145 -0
  193. package/test/functiondeclaration.test.tsx +327 -0
  194. package/test/imports.test.tsx +214 -0
  195. package/test/memberexpressions.test.tsx +725 -0
  196. package/test/namepolicies.test.tsx +109 -0
  197. package/test/pydocs.test.tsx +528 -0
  198. package/test/references.test.tsx +36 -0
  199. package/test/sourcefiles.test.tsx +131 -0
  200. package/test/utils.tsx +131 -0
  201. package/test/values.test.tsx +61 -0
  202. package/test/variables.test.tsx +153 -0
  203. package/tsconfig.json +12 -0
  204. package/tsdoc-metadata.json +11 -0
  205. package/vitest.config.ts +10 -0
  206. package/vitest.setup.ts +1 -0
@@ -0,0 +1,725 @@
1
+ import { code, memberRefkey, refkey } from "@alloy-js/core";
2
+ import { d } from "@alloy-js/core/testing";
3
+ import { describe, expect, it } from "vitest";
4
+ import * as py from "../src/index.js";
5
+ import {
6
+ ClassDeclaration,
7
+ FunctionDeclaration,
8
+ ParameterDescriptor,
9
+ SourceFile,
10
+ VariableDeclaration,
11
+ } from "../src/index.js";
12
+ import {
13
+ assertFileContents,
14
+ toSourceText,
15
+ toSourceTextMultiple,
16
+ } from "./utils.js";
17
+
18
+ it("renders basic member expression with dot notation", () => {
19
+ expect(
20
+ toSourceText([
21
+ <py.MemberExpression>
22
+ <py.MemberExpression.Part id="obj" />
23
+ <py.MemberExpression.Part id="property" />
24
+ </py.MemberExpression>,
25
+ ]),
26
+ ).toBe(d`
27
+ obj.property
28
+ `);
29
+ });
30
+
31
+ it("renders basic member expression with key", () => {
32
+ expect(
33
+ toSourceText([
34
+ <py.MemberExpression>
35
+ <py.MemberExpression.Part id="arr" />
36
+ <py.MemberExpression.Part key={12345} />
37
+ <py.MemberExpression.Part id="foo-bar" />
38
+ </py.MemberExpression>,
39
+ ]),
40
+ ).toBe(d`
41
+ arr[12345].foo-bar
42
+ `);
43
+ });
44
+
45
+ it("renders basic member expression with key with reference", () => {
46
+ const rk1 = refkey();
47
+ expect(
48
+ toSourceText([
49
+ <py.StatementList>
50
+ <py.VariableDeclaration name="test1" refkey={rk1} initializer={1} />
51
+ <py.MemberExpression>
52
+ <py.MemberExpression.Part id="arr" />
53
+ <py.MemberExpression.Part key={rk1} />
54
+ <py.MemberExpression.Part id="foo-bar" />
55
+ </py.MemberExpression>
56
+ </py.StatementList>,
57
+ ]),
58
+ ).toBe(d`
59
+ test1 = 1
60
+ arr[test1].foo-bar
61
+ `);
62
+ });
63
+
64
+ it("renders basic member expression with keys", () => {
65
+ expect(
66
+ toSourceText([
67
+ <py.MemberExpression>
68
+ <py.MemberExpression.Part id="arr" />
69
+ <py.MemberExpression.Part keys={[1, 2]} />
70
+ <py.MemberExpression.Part id="foo-bar" />
71
+ </py.MemberExpression>,
72
+ ]),
73
+ ).toBe(d`
74
+ arr[1, 2].foo-bar
75
+ `);
76
+ });
77
+
78
+ it("renders basic member expression with keys with references", () => {
79
+ const rk1 = refkey();
80
+ const rk2 = refkey();
81
+ expect(
82
+ toSourceText([
83
+ <py.StatementList>
84
+ <py.VariableDeclaration name="test1" refkey={rk1} initializer={1} />
85
+ <py.VariableDeclaration name="test2" refkey={rk2} initializer={2} />
86
+ <py.MemberExpression>
87
+ <py.MemberExpression.Part id="arr" />
88
+ <py.MemberExpression.Part keys={[rk1, rk2]} />
89
+ <py.MemberExpression.Part id="foo-bar" />
90
+ </py.MemberExpression>
91
+ </py.StatementList>,
92
+ ]),
93
+ ).toBe(d`
94
+ test1 = 1
95
+ test2 = 2
96
+ arr[test1, test2].foo-bar
97
+ `);
98
+ });
99
+
100
+ it("renders basic member expression with slice - 1", () => {
101
+ expect(
102
+ toSourceText([
103
+ <py.MemberExpression>
104
+ <py.MemberExpression.Part id="arr" />
105
+ <py.MemberExpression.Part slice={{ start: 1, stop: 3, step: 2 }} />
106
+ <py.MemberExpression.Part id="foo-bar" />
107
+ </py.MemberExpression>,
108
+ ]),
109
+ ).toBe(d`
110
+ arr[1:3:2].foo-bar
111
+ `);
112
+ });
113
+
114
+ it("renders basic member expression with slice - 1 with references", () => {
115
+ const rk1 = refkey();
116
+ const rk2 = refkey();
117
+ const rk3 = refkey();
118
+ expect(
119
+ toSourceText([
120
+ <py.StatementList>
121
+ <py.VariableDeclaration name="test1" refkey={rk1} initializer={1} />
122
+ <py.VariableDeclaration name="test2" refkey={rk2} initializer={3} />
123
+ <py.VariableDeclaration name="test3" refkey={rk3} initializer={2} />
124
+ <py.MemberExpression>
125
+ <py.MemberExpression.Part id="arr" />
126
+ <py.MemberExpression.Part
127
+ slice={{ start: rk1, stop: rk2, step: rk3 }}
128
+ />
129
+ <py.MemberExpression.Part id="foo-bar" />
130
+ </py.MemberExpression>
131
+ </py.StatementList>,
132
+ ]),
133
+ ).toBe(d`
134
+ test1 = 1
135
+ test2 = 3
136
+ test3 = 2
137
+ arr[test1:test2:test3].foo-bar
138
+ `);
139
+ });
140
+
141
+ it("renders basic member expression with slice - 2", () => {
142
+ expect(
143
+ toSourceText([
144
+ <py.MemberExpression>
145
+ <py.MemberExpression.Part id="arr" />
146
+ <py.MemberExpression.Part slice={{ stop: 3 }} />
147
+ <py.MemberExpression.Part id="foo-bar" />
148
+ </py.MemberExpression>,
149
+ ]),
150
+ ).toBe(d`
151
+ arr[:3].foo-bar
152
+ `);
153
+ });
154
+
155
+ it("renders basic member expression with slice - 3", () => {
156
+ expect(
157
+ toSourceText([
158
+ <py.MemberExpression>
159
+ <py.MemberExpression.Part id="arr" />
160
+ <py.MemberExpression.Part slice={{ step: 2 }} />
161
+ <py.MemberExpression.Part id="foo-bar" />
162
+ </py.MemberExpression>,
163
+ ]),
164
+ ).toBe(d`
165
+ arr[::2].foo-bar
166
+ `);
167
+ });
168
+
169
+ it("renders basic member expression with slice - 4", () => {
170
+ expect(
171
+ toSourceText([
172
+ <py.MemberExpression>
173
+ <py.MemberExpression.Part id="arr" />
174
+ <py.MemberExpression.Part slice={{ start: 1 }} />
175
+ <py.MemberExpression.Part id="foo-bar" />
176
+ </py.MemberExpression>,
177
+ ]),
178
+ ).toBe(d`
179
+ arr[1:].foo-bar
180
+ `);
181
+ });
182
+
183
+ it("renders basic member expression with slice - 5", () => {
184
+ expect(
185
+ toSourceText([
186
+ <py.MemberExpression>
187
+ <py.MemberExpression.Part id="arr" />
188
+ <py.MemberExpression.Part slice={{ start: 1, step: 2 }} />
189
+ <py.MemberExpression.Part id="foo-bar" />
190
+ </py.MemberExpression>,
191
+ ]),
192
+ ).toBe(d`
193
+ arr[1::2].foo-bar
194
+ `);
195
+ });
196
+
197
+ it("renders basic member expression with an expression index - 1", () => {
198
+ const xRefkey = refkey();
199
+ expect(
200
+ toSourceText([
201
+ <py.StatementList>
202
+ <py.VariableDeclaration name="x" initializer={1} refkey={xRefkey} />
203
+ <py.MemberExpression>
204
+ <py.MemberExpression.Part id="arr" />
205
+ <py.MemberExpression.Part key={code`${xRefkey} + 1`} />
206
+ <py.MemberExpression.Part id="foo-bar" />
207
+ </py.MemberExpression>
208
+ </py.StatementList>,
209
+ ]),
210
+ ).toBe(d`
211
+ x = 1
212
+ arr[x + 1].foo-bar
213
+ `);
214
+ });
215
+
216
+ it("renders basic member expression with an expression index - 2", () => {
217
+ expect(
218
+ toSourceText([
219
+ <py.StatementList>
220
+ <py.MemberExpression>
221
+ <py.MemberExpression.Part id="arr" />
222
+ <py.MemberExpression.Part key={code`"foo" + 1`} />
223
+ <py.MemberExpression.Part id="foo-bar" />
224
+ </py.MemberExpression>
225
+ </py.StatementList>,
226
+ ]),
227
+ ).toBe(d`
228
+ arr["foo" + 1].foo-bar
229
+ `);
230
+ });
231
+
232
+ it("throws an error for invalid identifiers with quotes", () => {
233
+ expect(() =>
234
+ toSourceText([
235
+ <py.MemberExpression>
236
+ <py.MemberExpression.Part id="obj" />
237
+ <py.MemberExpression.Part id={`property-"name"`} />
238
+ </py.MemberExpression>,
239
+ ]),
240
+ ).toThrowError(/Invalid identifier: property-"name"/);
241
+ });
242
+
243
+ it("supports multiple levels of nesting", () => {
244
+ expect(
245
+ toSourceText([
246
+ <py.MemberExpression>
247
+ <py.MemberExpression.Part id="a" />
248
+ <py.MemberExpression.Part id="b" />
249
+ <py.MemberExpression.Part id="c" />
250
+ <py.MemberExpression.Part id="d" />
251
+ </py.MemberExpression>,
252
+ ]),
253
+ ).toBe(d`
254
+ a.b.c.d
255
+ `);
256
+ });
257
+
258
+ it("handles a mix of dot and bracket notation", () => {
259
+ expect(
260
+ toSourceText([
261
+ <py.MemberExpression>
262
+ <py.MemberExpression.Part id="obj" />
263
+ <py.MemberExpression.Part id="normalProp" />
264
+ <py.MemberExpression.Part key={"special-prop"} />
265
+ <py.MemberExpression.Part key={"123"} />
266
+ </py.MemberExpression>,
267
+ ]),
268
+ ).toBe(d`
269
+ obj.normalProp["special-prop"]["123"]
270
+ `);
271
+ });
272
+
273
+ it("throws an error when providing conflicting part props", () => {
274
+ expect(() =>
275
+ toSourceText([
276
+ <py.MemberExpression>
277
+ <py.MemberExpression.Part id="obj" />
278
+ <py.MemberExpression.Part id="property" args={[1, 2]} />
279
+ </py.MemberExpression>,
280
+ ]),
281
+ ).toThrowError(
282
+ `Only one of args, id can be used for a MemberExpression part at a time`,
283
+ );
284
+ });
285
+
286
+ it("throws an error when providing an empty slice", () => {
287
+ expect(() =>
288
+ toSourceText([
289
+ <py.MemberExpression>
290
+ <py.MemberExpression.Part id="obj" />
291
+ <py.MemberExpression.Part slice={{}} />
292
+ </py.MemberExpression>,
293
+ ]),
294
+ ).toThrowError(`MemberExpression.Part: slice object cannot be empty`);
295
+ });
296
+
297
+ it("throws an error when providing an empty array", () => {
298
+ expect(() =>
299
+ toSourceText([
300
+ <py.MemberExpression>
301
+ <py.MemberExpression.Part id="obj" />
302
+ <py.MemberExpression.Part keys={[]} />
303
+ </py.MemberExpression>,
304
+ ]),
305
+ ).toThrowError(`MemberExpression.Part: keys array cannot be empty`);
306
+ });
307
+
308
+ it("takes children for the id part", () => {
309
+ expect(
310
+ toSourceText([
311
+ <py.StatementList>
312
+ <py.MemberExpression>
313
+ <py.MemberExpression.Part id="child1" />
314
+ <py.MemberExpression.Part key={"child1"} />
315
+ </py.MemberExpression>
316
+ <py.MemberExpression>
317
+ <py.MemberExpression.Part id="child1" />
318
+ <py.MemberExpression.Part key={"child2"} />
319
+ <py.MemberExpression.Part args />
320
+ <py.MemberExpression.Part key={"child3"} />
321
+ <py.MemberExpression.Part args />
322
+ <py.MemberExpression.Part key={code`"foo" + 1`} />
323
+ <py.MemberExpression.Part args />
324
+ </py.MemberExpression>
325
+ </py.StatementList>,
326
+ ]),
327
+ ).toBe(d`
328
+ child1["child1"]
329
+ child1["child2"]()["child3"]()["foo" + 1]()
330
+ `);
331
+ });
332
+
333
+ describe("with refkeys", () => {
334
+ it("handles symbols correctly", () => {
335
+ const rk1 = refkey();
336
+ const rk2 = refkey();
337
+ expect(
338
+ toSourceText([
339
+ <py.StatementList>
340
+ <py.VariableDeclaration name="test1" refkey={rk1} initializer={1} />
341
+ <py.VariableDeclaration name="test1" refkey={rk2} initializer={2} />
342
+ <py.MemberExpression>
343
+ <py.MemberExpression.Part refkey={rk1} />
344
+ <py.MemberExpression.Part refkey={rk2} />
345
+ </py.MemberExpression>
346
+ </py.StatementList>,
347
+ ]),
348
+ ).toBe(d`
349
+ test1 = 1
350
+ test1_2_test = 2
351
+ test1.test1_2_test
352
+ `);
353
+ });
354
+
355
+ it("Correctly resolves member expressions from 2 different classes", () => {
356
+ const model1Ref = refkey();
357
+ const model2Ref = refkey();
358
+ const classMethod1Ref = refkey();
359
+ const classMethod2Ref = refkey();
360
+ const v1Rk = refkey();
361
+ const v2Rk = refkey();
362
+ const template = (
363
+ <py.StatementList>
364
+ <ClassDeclaration name="Model1" refkey={model1Ref}>
365
+ <VariableDeclaration
366
+ name="foo"
367
+ refkey={classMethod1Ref}
368
+ type="str"
369
+ omitNone={true}
370
+ instanceVariable={true}
371
+ />
372
+ </ClassDeclaration>
373
+ <ClassDeclaration name="Model2" refkey={model2Ref}>
374
+ <VariableDeclaration
375
+ name="bar"
376
+ refkey={classMethod2Ref}
377
+ type="str"
378
+ omitNone={true}
379
+ instanceVariable={true}
380
+ />
381
+ </ClassDeclaration>
382
+ <py.VariableDeclaration
383
+ name="model1_instance"
384
+ refkey={v1Rk}
385
+ type={model1Ref}
386
+ initializer={
387
+ <py.MemberExpression>
388
+ <py.MemberExpression.Part refkey={model1Ref} />
389
+ <py.MemberExpression.Part args />
390
+ </py.MemberExpression>
391
+ }
392
+ />
393
+ <py.VariableDeclaration
394
+ name="model2_instance"
395
+ refkey={v2Rk}
396
+ type={model2Ref}
397
+ initializer={
398
+ <py.MemberExpression>
399
+ <py.MemberExpression.Part refkey={model2Ref} />
400
+ <py.MemberExpression.Part args />
401
+ </py.MemberExpression>
402
+ }
403
+ />
404
+ <>{memberRefkey(v1Rk, classMethod1Ref)}</>
405
+ <>{memberRefkey(v2Rk, classMethod2Ref)}</>
406
+ </py.StatementList>
407
+ );
408
+
409
+ expect(toSourceText([template])).toBe(d`
410
+ class Model1:
411
+ foo: str
412
+
413
+ class Model2:
414
+ bar: str
415
+
416
+ model1_instance: Model1 = Model1()
417
+ model2_instance: Model2 = Model2()
418
+ model1_instance.foo
419
+ model2_instance.bar
420
+ `);
421
+ });
422
+
423
+ it("handles optional parameters correctly", () => {
424
+ const fooRef = refkey();
425
+ const modelRef = refkey();
426
+ const parameters: ParameterDescriptor[] = [
427
+ { name: "foo", optional: true, refkey: fooRef, type: modelRef },
428
+ ];
429
+ const messageRef = refkey();
430
+ const template = (
431
+ <py.StatementList>
432
+ <ClassDeclaration name="Model" refkey={modelRef}>
433
+ <VariableDeclaration
434
+ name="bar"
435
+ refkey={refkey()}
436
+ type="str"
437
+ omitNone={true}
438
+ />
439
+ </ClassDeclaration>
440
+ <FunctionDeclaration name="fooFunction" parameters={parameters}>
441
+ <py.StatementList>
442
+ <py.VariableDeclaration
443
+ name="message"
444
+ refkey={messageRef}
445
+ initializer={
446
+ <py.MemberExpression>
447
+ <py.MemberExpression.Part refkey={fooRef} />
448
+ <py.MemberExpression.Part id="bar" />
449
+ </py.MemberExpression>
450
+ }
451
+ />
452
+ <>print({messageRef})</>
453
+ </py.StatementList>
454
+ </FunctionDeclaration>
455
+ </py.StatementList>
456
+ );
457
+
458
+ expect(toSourceText([template])).toBe(d`
459
+ class Model:
460
+ bar: str
461
+
462
+ def foo_function(foo: Model = None):
463
+ message = foo.bar
464
+ print(message)
465
+
466
+ `);
467
+ });
468
+
469
+ it("handles class member correctly", () => {
470
+ const classRefkey = refkey();
471
+ const interfaceRefkey = refkey();
472
+ const interfaceMemberRefkey = refkey();
473
+ const classMethodRefkey = refkey();
474
+ const classMemberRefkey = refkey();
475
+ const instanceRefkey = refkey();
476
+ expect(
477
+ toSourceText([
478
+ <py.StatementList>
479
+ <ClassDeclaration name="Bar" refkey={interfaceRefkey}>
480
+ <VariableDeclaration
481
+ name="prop1"
482
+ refkey={interfaceMemberRefkey}
483
+ type={"str"}
484
+ omitNone={true}
485
+ />
486
+ </ClassDeclaration>
487
+ <ClassDeclaration name="Foo" refkey={classRefkey}>
488
+ <VariableDeclaration
489
+ name="test1"
490
+ refkey={classMemberRefkey}
491
+ type={interfaceRefkey}
492
+ />
493
+ <br />
494
+ <FunctionDeclaration
495
+ name="testMethod"
496
+ parameters={[]}
497
+ refkey={classMethodRefkey}
498
+ returnType={interfaceRefkey}
499
+ />
500
+ </ClassDeclaration>
501
+ <py.VariableDeclaration
502
+ name="inst"
503
+ refkey={instanceRefkey}
504
+ initializer={code`${classRefkey}()`}
505
+ />
506
+ <py.MemberExpression>
507
+ <py.MemberExpression.Part refkey={instanceRefkey} />
508
+ <py.MemberExpression.Part refkey={classMemberRefkey} />
509
+ <py.MemberExpression.Part refkey={interfaceMemberRefkey} />
510
+ </py.MemberExpression>
511
+ <py.MemberExpression>
512
+ <py.MemberExpression.Part refkey={instanceRefkey} />
513
+ <py.MemberExpression.Part refkey={classMethodRefkey} />
514
+ <py.MemberExpression.Part args={[]} />
515
+ </py.MemberExpression>
516
+ </py.StatementList>,
517
+ ]),
518
+ ).toBe(d`
519
+ class Bar:
520
+ prop1: str
521
+
522
+ class Foo:
523
+ test1: Bar = None
524
+ def test_method() -> Bar:
525
+ pass
526
+
527
+
528
+ inst = Foo()
529
+ inst.test1.prop1
530
+ inst.test_method()
531
+ `);
532
+ });
533
+
534
+ it("handles late resolved refkeys correctly", () => {
535
+ const rk1 = refkey();
536
+ const rk2 = refkey();
537
+ expect(
538
+ toSourceText([
539
+ <py.StatementList>
540
+ <py.MemberExpression>
541
+ <py.MemberExpression.Part refkey={rk1} />
542
+ <py.MemberExpression.Part refkey={rk2} />
543
+ </py.MemberExpression>
544
+ <py.VariableDeclaration name="test1" refkey={rk1} initializer={1} />
545
+ <py.VariableDeclaration name="test1" refkey={rk2} initializer={2} />
546
+ </py.StatementList>,
547
+ ]),
548
+ ).toBe(d`
549
+ test1.test1_2_test
550
+ test1 = 1
551
+ test1_2_test = 2
552
+ `);
553
+ });
554
+
555
+ it("creates a full reference to the first refkey", () => {
556
+ const rk1 = refkey();
557
+ const res = toSourceTextMultiple([
558
+ <SourceFile path="source.py">
559
+ <py.VariableDeclaration name="importMe" refkey={rk1} />
560
+ </SourceFile>,
561
+ <SourceFile path="index.py">
562
+ <py.StatementList>
563
+ <py.MemberExpression>
564
+ <py.MemberExpression.Part refkey={rk1} />
565
+ <py.MemberExpression.Part id="foo" />
566
+ </py.MemberExpression>
567
+ </py.StatementList>
568
+ </SourceFile>,
569
+ ]);
570
+
571
+ assertFileContents(res, {
572
+ "index.py": d`
573
+ from source import import_me
574
+
575
+ import_me.foo
576
+ `,
577
+ });
578
+ });
579
+ });
580
+
581
+ describe("with function calls", () => {
582
+ it("handles simple function calls correctly", () => {
583
+ expect(
584
+ toSourceText([
585
+ <py.MemberExpression>
586
+ <py.MemberExpression.Part id="myFunction" />
587
+ <py.MemberExpression.Part args={[1, 2]} />
588
+ </py.MemberExpression>,
589
+ ]),
590
+ ).toBe(d`
591
+ myFunction(1, 2)
592
+ `);
593
+ });
594
+
595
+ it("handles function calls with references correctly", () => {
596
+ const xRefkey = refkey();
597
+ const yRefkey = refkey();
598
+ expect(
599
+ toSourceText([
600
+ <py.StatementList>
601
+ <py.VariableDeclaration name="x" initializer={1} refkey={xRefkey} />
602
+ <py.VariableDeclaration name="y" initializer={2} refkey={yRefkey} />
603
+ <py.MemberExpression>
604
+ <py.MemberExpression.Part id="myFunction" />
605
+ <py.MemberExpression.Part args={[xRefkey, yRefkey]} />
606
+ </py.MemberExpression>
607
+ </py.StatementList>,
608
+ ]),
609
+ ).toBe(d`
610
+ x = 1
611
+ y = 2
612
+ myFunction(x, y)
613
+ `);
614
+ });
615
+
616
+ it("handles method calls correctly", () => {
617
+ expect(
618
+ toSourceText([
619
+ <py.MemberExpression>
620
+ <py.MemberExpression.Part id="method1" />
621
+ <py.MemberExpression.Part args={[1, 2]} />
622
+ <py.MemberExpression.Part args={[]} />
623
+ <py.MemberExpression.Part id="method2" />
624
+ <py.MemberExpression.Part args={[]} />
625
+ <py.MemberExpression.Part id="prop" />
626
+ </py.MemberExpression>,
627
+ ]),
628
+ ).toBe(d`
629
+ method1(1, 2)().method2().prop
630
+ `);
631
+ });
632
+
633
+ it("handles function calls correctly", () => {
634
+ expect(
635
+ toSourceText([
636
+ <py.MemberExpression>
637
+ <py.MemberExpression.Part id="myFunction" />
638
+ <py.MemberExpression.Part args={[1, 2]} />
639
+ <py.MemberExpression.Part id="prop" />
640
+ </py.MemberExpression>,
641
+ ]),
642
+ ).toBe(d`
643
+ myFunction(1, 2).prop
644
+ `);
645
+ });
646
+
647
+ it("handles function calls correctly", () => {
648
+ expect(
649
+ toSourceText([
650
+ <py.MemberExpression>
651
+ <py.MemberExpression.Part id="myFunction" />
652
+ <py.MemberExpression.Part args={[1, 2]} />
653
+ <py.MemberExpression.Part id="prop" />
654
+ </py.MemberExpression>,
655
+ ]),
656
+ ).toBe(d`
657
+ myFunction(1, 2).prop
658
+ `);
659
+ });
660
+ });
661
+
662
+ describe("formatting", () => {
663
+ describe("simple chains", () => {
664
+ it("just dots", () => {
665
+ expect(
666
+ toSourceText(
667
+ [
668
+ <py.MemberExpression>
669
+ <py.MemberExpression.Part id="four" />
670
+ <py.MemberExpression.Part id="four" />
671
+ <py.MemberExpression.Part id="two" />
672
+ <py.MemberExpression.Part id="two" />
673
+ <py.MemberExpression.Part id="two" />
674
+ <py.MemberExpression.Part id="two" />
675
+ </py.MemberExpression>,
676
+ ],
677
+ { printOptions: { printWidth: 14 } },
678
+ ),
679
+ ).toBe(d`
680
+ four.four \\
681
+ .two.two \\
682
+ .two.two
683
+ `);
684
+ });
685
+
686
+ it("bracket breaks", () => {
687
+ expect(
688
+ toSourceText(
689
+ [
690
+ <py.MemberExpression>
691
+ <py.MemberExpression.Part id="obj" />
692
+ <py.MemberExpression.Part key={"property-name"} />
693
+ <py.MemberExpression.Part id="prop" />
694
+ </py.MemberExpression>,
695
+ ],
696
+ { printOptions: { printWidth: 12 } },
697
+ ),
698
+ ).toBe(d`
699
+ obj[
700
+ "property-name"
701
+ ].prop
702
+ `);
703
+ });
704
+ });
705
+
706
+ describe("call chains", () => {
707
+ it("renders multiple calls on the same line when there are no breaks and they fit", () => {
708
+ expect(
709
+ toSourceText([
710
+ <py.MemberExpression>
711
+ <py.MemberExpression.Part id="z" />
712
+ <py.MemberExpression.Part id="object" />
713
+ <py.MemberExpression.Part args />
714
+ <py.MemberExpression.Part id="partial" />
715
+ <py.MemberExpression.Part args />
716
+ <py.MemberExpression.Part id="optional" />
717
+ <py.MemberExpression.Part args />
718
+ </py.MemberExpression>,
719
+ ]),
720
+ ).toBe(d`
721
+ z.object().partial().optional()
722
+ `);
723
+ });
724
+ });
725
+ });