@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,109 @@
1
+ import { d } from "@alloy-js/core/testing";
2
+ import { expect, it } from "vitest";
3
+ import { enumModule } from "../src/builtins/python.js";
4
+ import * as py from "../src/index.js";
5
+ import { toSourceText } from "./utils.jsx";
6
+
7
+ it("correct formatting of class name", () => {
8
+ const result = toSourceText([
9
+ <py.ClassDeclaration name="a-really-WeirdClass-name" />,
10
+ ]);
11
+ const expected = d`
12
+ class AReallyWeirdClassName:
13
+ pass
14
+
15
+
16
+ `;
17
+ expect(result).toRenderTo(expected);
18
+ });
19
+
20
+ it("correct formatting of Enum name and EnumMember names", () => {
21
+ const result = toSourceText(
22
+ [
23
+ <py.EnumDeclaration
24
+ name="priority"
25
+ style="functional"
26
+ members={[
27
+ { name: "high", value: 1 },
28
+ { name: "Medium", value: 2 },
29
+ { name: "lowValue", value: 3 },
30
+ ]}
31
+ />,
32
+ ],
33
+ { externals: [enumModule] },
34
+ );
35
+ const expected = d`
36
+ from enum import Enum
37
+
38
+ Priority = Enum('Priority', {'HIGH' : 1, 'MEDIUM' : 2, 'LOW_VALUE' : 3})
39
+ `;
40
+ expect(result).toRenderTo(expected);
41
+ });
42
+
43
+ it("renders a function with parameters", () => {
44
+ const result = toSourceText([
45
+ <py.FunctionDeclaration
46
+ name="quirklyNamed-Function"
47
+ parameters={[{ name: "a-parameter", type: "int" }]}
48
+ args={true}
49
+ kwargs={true}
50
+ >
51
+ print(x, y)
52
+ </py.FunctionDeclaration>,
53
+ ]);
54
+ expect(result).toRenderTo(
55
+ d`
56
+ def quirkly_named_function(a_parameter: int, *args, **kwargs):
57
+ print(x, y)
58
+
59
+
60
+ `,
61
+ );
62
+ });
63
+
64
+ it("correct formatting of call signature parameters names", () => {
65
+ const result = toSourceText([
66
+ <py.CallSignatureParameters
67
+ parameters={[
68
+ { name: "this-is-a-number", type: "int" },
69
+ {
70
+ name: "andThisIsADict",
71
+ type: "dict",
72
+ },
73
+ ]}
74
+ />,
75
+ ]);
76
+ expect(result).toRenderTo(`this_is_a_number: int, and_this_is_a_dict: dict`);
77
+ });
78
+
79
+ it("correct formatting of call statement vars", () => {
80
+ const result = toSourceText([
81
+ <py.StatementList>
82
+ <py.ClassInstantiation
83
+ target={"test"}
84
+ args={[
85
+ <py.VariableDeclaration
86
+ name="this-is-a-long-name"
87
+ initializer={<py.Atom jsValue={"A name"} />}
88
+ callStatementVar
89
+ />,
90
+ <py.VariableDeclaration
91
+ name="andThisIsANumber"
92
+ initializer={<py.Atom jsValue={42} />}
93
+ callStatementVar
94
+ />,
95
+ ]}
96
+ />
97
+ </py.StatementList>,
98
+ ]);
99
+ expect(result).toRenderTo(
100
+ `test(this_is_a_long_name="A name", and_this_is_a_number=42)`,
101
+ );
102
+ });
103
+
104
+ it("correct formatting of variable name", () => {
105
+ const res = toSourceText([
106
+ <py.VariableDeclaration name="myVar" type="int" initializer={42} />,
107
+ ]);
108
+ expect(res).toBe(`my_var: int = 42`);
109
+ });
@@ -0,0 +1,528 @@
1
+ import { Prose } from "@alloy-js/core";
2
+ import { d } from "@alloy-js/core/testing";
3
+ import { describe, expect, it } from "vitest";
4
+ import { enumModule } from "../src/builtins/python.js";
5
+ import * as py from "../src/index.js";
6
+ import { toSourceText } from "./utils.jsx";
7
+
8
+ describe("PyDoc", () => {
9
+ it("formats properly", () => {
10
+ const res = toSourceText(
11
+ [
12
+ <py.PyDoc>
13
+ <Prose>
14
+ This is an example of a long docstring that will be broken in lines.
15
+ We will also render another paragraph after this one.
16
+ </Prose>
17
+ <Prose>
18
+ This is another paragraph, and there's a line break before it.
19
+ </Prose>
20
+ </py.PyDoc>,
21
+ ],
22
+ { printOptions: { printWidth: 40 } },
23
+ );
24
+
25
+ expect(res).toRenderTo(
26
+ d`
27
+ """
28
+ This is an example of a long docstring
29
+ that will be broken in lines. We will
30
+ also render another paragraph after this
31
+ one.
32
+
33
+ This is another paragraph, and there's a
34
+ line break before it.
35
+ """
36
+
37
+
38
+ `,
39
+ );
40
+ });
41
+ });
42
+
43
+ describe("PyDocExample", () => {
44
+ it("creates docstring with a code sample", () => {
45
+ const res = toSourceText(
46
+ [
47
+ <py.PyDoc>
48
+ <Prose>This is an example of a docstring with a code sample.</Prose>
49
+ <py.PyDocExample>print("Hello world!")</py.PyDocExample>
50
+ </py.PyDoc>,
51
+ ],
52
+ { printOptions: { printWidth: 40 } },
53
+ );
54
+
55
+ expect(res).toRenderTo(
56
+ d`
57
+ """
58
+ This is an example of a docstring with a
59
+ code sample.
60
+
61
+ >> print("Hello world!")
62
+ """
63
+
64
+
65
+ `,
66
+ );
67
+ });
68
+
69
+ it("creates docstring with more than one code sample", () => {
70
+ const res = toSourceText(
71
+ [
72
+ <py.PyDoc>
73
+ <Prose>This is an example of a docstring with a code sample.</Prose>
74
+ <py.PyDocExample>print("Hello world!")</py.PyDocExample>
75
+ <py.PyDocExample>print("Hello world again!")</py.PyDocExample>
76
+ </py.PyDoc>,
77
+ ],
78
+ { printOptions: { printWidth: 40 } },
79
+ );
80
+
81
+ expect(res).toRenderTo(
82
+ d`
83
+ """
84
+ This is an example of a docstring with a
85
+ code sample.
86
+
87
+ >> print("Hello world!")
88
+
89
+ >> print("Hello world again!")
90
+ """
91
+
92
+
93
+ `,
94
+ );
95
+ });
96
+
97
+ it("creates docstring with a multiline code sample", () => {
98
+ const res = toSourceText(
99
+ [
100
+ <py.PyDoc>
101
+ <Prose>This is an example of a docstring with a code sample.</Prose>
102
+ <py.PyDocExample>
103
+ print("Hello world!")
104
+ <br />
105
+ x = "Hello"
106
+ <br />
107
+ print(x)
108
+ </py.PyDocExample>
109
+ </py.PyDoc>,
110
+ ],
111
+ { printOptions: { printWidth: 40 } },
112
+ );
113
+
114
+ expect(res).toRenderTo(
115
+ d`
116
+ """
117
+ This is an example of a docstring with a
118
+ code sample.
119
+
120
+ >> print("Hello world!")
121
+ >> x = "Hello"
122
+ >> print(x)
123
+ """
124
+
125
+
126
+ `,
127
+ );
128
+ });
129
+ });
130
+
131
+ describe("GoogleStyleDocParam", () => {
132
+ it("name only", () => {
133
+ const res = toSourceText([
134
+ <py.PyDoc>
135
+ <py.GoogleStyleDocParam name="somebody" />
136
+ </py.PyDoc>,
137
+ ]);
138
+ expect(res).toRenderTo(
139
+ d`
140
+ """
141
+ somebody
142
+ """
143
+
144
+
145
+ `,
146
+ );
147
+ });
148
+ it("name and type", () => {
149
+ const res = toSourceText([
150
+ <py.PyDoc>
151
+ <py.GoogleStyleDocParam name="somebody" type="str" />
152
+ </py.PyDoc>,
153
+ ]);
154
+ expect(res).toRenderTo(
155
+ d`
156
+ """
157
+ somebody (str)
158
+ """
159
+
160
+
161
+ `,
162
+ );
163
+ });
164
+ it("name, type and description", () => {
165
+ const res = toSourceText([
166
+ <py.PyDoc>
167
+ <py.GoogleStyleDocParam name="somebody" type="str">
168
+ Somebody's name.
169
+ </py.GoogleStyleDocParam>
170
+ </py.PyDoc>,
171
+ ]);
172
+ expect(res).toRenderTo(
173
+ d`
174
+ """
175
+ somebody (str): Somebody's name.
176
+ """
177
+
178
+
179
+ `,
180
+ );
181
+ });
182
+ it("name, type, description, and optional", () => {
183
+ const res = toSourceText([
184
+ <py.PyDoc>
185
+ <py.GoogleStyleDocParam name="somebody" type="str" optional>
186
+ Somebody's name.
187
+ </py.GoogleStyleDocParam>
188
+ </py.PyDoc>,
189
+ ]);
190
+ expect(res).toRenderTo(
191
+ d`
192
+ """
193
+ somebody (str, optional): Somebody's name.
194
+ """
195
+
196
+
197
+ `,
198
+ );
199
+ });
200
+ it("name, type, description, and optional with default value", () => {
201
+ const res = toSourceText([
202
+ <py.PyDoc>
203
+ <py.GoogleStyleDocParam
204
+ name="somebody"
205
+ type="str"
206
+ optional
207
+ defaultValue="John Doe"
208
+ >
209
+ Somebody's name.
210
+ </py.GoogleStyleDocParam>
211
+ </py.PyDoc>,
212
+ ]);
213
+ expect(res).toRenderTo(
214
+ d`
215
+ """
216
+ somebody (str, optional): Somebody's name. Defaults to \"John Doe\".
217
+ """
218
+
219
+
220
+ `,
221
+ );
222
+ });
223
+ it("name, type, description, and optional with default value with a very long description", () => {
224
+ const res = toSourceText(
225
+ [
226
+ <py.PyDoc>
227
+ <py.GoogleStyleDocParam
228
+ name="somebody"
229
+ type="str"
230
+ optional
231
+ defaultValue="John Doe"
232
+ >
233
+ Somebody's name. This can be any string representing a person,
234
+ whether it's a first name, full name, nickname, or even a codename
235
+ (e.g., "Agent X"). It's used primarily for display purposes,
236
+ logging, or greeting messages and is not required to be unique or
237
+ validated unless specified by the caller.
238
+ </py.GoogleStyleDocParam>
239
+ <py.GoogleStyleDocParam name="somebody2" type="str">
240
+ Somebody's name. This can be any string representing a person,
241
+ whether it's a first name, full name, nickname, or even a codename
242
+ (e.g., "Agent X"). It's used primarily for display purposes,
243
+ logging, or greeting messages and is not required to be unique or
244
+ validated unless specified by the caller.
245
+ </py.GoogleStyleDocParam>
246
+ </py.PyDoc>,
247
+ ],
248
+ { printOptions: { printWidth: 80 } },
249
+ );
250
+ expect(res).toRenderTo(
251
+ d`
252
+ """
253
+ somebody (str, optional): Somebody's name. This can be any string representing a
254
+ person, whether it's a first name, full name, nickname, or even a codename
255
+ (e.g., "Agent X"). It's used primarily for display purposes, logging, or
256
+ greeting messages and is not required to be unique or validated unless
257
+ specified by the caller. Defaults to \"John Doe\".
258
+
259
+ somebody2 (str): Somebody's name. This can be any string representing a person,
260
+ whether it's a first name, full name, nickname, or even a codename (e.g.,
261
+ "Agent X"). It's used primarily for display purposes, logging, or greeting
262
+ messages and is not required to be unique or validated unless specified by
263
+ the caller.
264
+ """
265
+
266
+
267
+ `,
268
+ );
269
+ });
270
+ it("name, type, description, and optional with default value with a description containing a linebreak", () => {
271
+ const res = toSourceText(
272
+ [
273
+ <py.PyDoc>
274
+ <py.GoogleStyleDocParam
275
+ name="somebody"
276
+ type="str"
277
+ optional
278
+ defaultValue="John Doe"
279
+ >
280
+ Somebody's name. This is one line
281
+ <hbr />
282
+ This is another line.
283
+ </py.GoogleStyleDocParam>
284
+ </py.PyDoc>,
285
+ ],
286
+ { printOptions: { printWidth: 80 } },
287
+ );
288
+ expect(res).toRenderTo(
289
+ d`
290
+ """
291
+ somebody (str, optional): Somebody's name. This is one line
292
+ This is another line. Defaults to \"John Doe\".
293
+ """
294
+
295
+
296
+ `,
297
+ );
298
+ });
299
+ });
300
+
301
+ describe("Full example", () => {
302
+ it("renders correctly in a Class", () => {
303
+ const doc = (
304
+ <py.ClassDoc
305
+ description={[
306
+ <Prose>
307
+ This is an example of a long docstring that will be broken in lines.
308
+ We will also render another paragraph after this one.
309
+ </Prose>,
310
+ <py.PyDocExample>
311
+ print("Hello world!")
312
+ <br />
313
+ x = "Hello"
314
+ <br />
315
+ print(x)
316
+ </py.PyDocExample>,
317
+ ]}
318
+ parameters={[
319
+ {
320
+ name: "somebody",
321
+ type: "str",
322
+ optional: true,
323
+ default: "John Doe",
324
+ doc: "Somebody's name. This can be any string representing a person, whether it's a first name, full name, nickname, or even a codename (e.g., 'Agent X'). It's used primarily for display purposes, logging, or greeting messages and is not required to be unique or validated unless specified by the caller. Defaults to \"John Doe\".",
325
+ },
326
+ {
327
+ name: "somebody2",
328
+ type: "str",
329
+ doc: "Somebody's name. This can be any string representing a person, whether it's a first name, full name, nickname, or even a codename (e.g., 'Agent X'). It's used primarily for display purposes, logging, or greeting messages and is not required to be unique or validated unless specified by the caller.",
330
+ },
331
+ ]}
332
+ style="google"
333
+ />
334
+ );
335
+ const res = toSourceText(
336
+ [
337
+ <py.ClassDeclaration name="A" doc={doc}>
338
+ <py.StatementList>
339
+ <py.VariableDeclaration name="just_name" />
340
+ <py.VariableDeclaration name="name_and_type" type="number" />
341
+ <py.VariableDeclaration
342
+ name="name_type_and_value"
343
+ type="number"
344
+ initializer={12}
345
+ />
346
+ </py.StatementList>
347
+ </py.ClassDeclaration>,
348
+ ],
349
+ { printOptions: { printWidth: 80, tabWidth: 4 } },
350
+ );
351
+
352
+ expect(res).toRenderTo(
353
+ d`
354
+ class A:
355
+ """
356
+ This is an example of a long docstring that will be broken in lines. We will
357
+ also render another paragraph after this one.
358
+
359
+ >> print("Hello world!")
360
+ >> x = "Hello"
361
+ >> print(x)
362
+
363
+ Args:
364
+ somebody (str, optional): Somebody's name. This can be any string
365
+ representing a person, whether it's a first name, full name,
366
+ nickname, or even a codename (e.g., 'Agent X'). It's used primarily
367
+ for display purposes, logging, or greeting messages and is not
368
+ required to be unique or validated unless specified by the caller.
369
+ Defaults to \"John Doe\".
370
+
371
+ somebody2 (str): Somebody's name. This can be any string representing a
372
+ person, whether it's a first name, full name, nickname, or even a
373
+ codename (e.g., 'Agent X'). It's used primarily for display
374
+ purposes, logging, or greeting messages and is not required to be
375
+ unique or validated unless specified by the caller.
376
+ """
377
+ just_name = None
378
+ name_and_type: number = None
379
+ name_type_and_value: number = 12
380
+
381
+
382
+ `,
383
+ );
384
+ });
385
+
386
+ it("renders correctly in a Function", () => {
387
+ const doc = (
388
+ <py.FunctionDoc
389
+ description={[
390
+ <Prose>
391
+ This is an example of a long docstring that will be broken in lines.
392
+ We will also render another paragraph after this one.
393
+ </Prose>,
394
+ <py.PyDocExample>
395
+ print("Hello world!")
396
+ <br />
397
+ x = "Hello"
398
+ <br />
399
+ print(x)
400
+ </py.PyDocExample>,
401
+ ]}
402
+ parameters={[
403
+ {
404
+ name: "somebody",
405
+ type: "str",
406
+ optional: true,
407
+ default: "John Doe",
408
+ doc: "Somebody's name. This can be any string representing a person, whether it's a first name, full name, nickname, or even a codename (e.g., 'Agent X'). It's used primarily for display purposes, logging, or greeting messages and is not required to be unique or validated unless specified by the caller. Defaults to \"John Doe\".",
409
+ },
410
+ {
411
+ name: "somebody2",
412
+ type: "str",
413
+ doc: "Somebody's name. This can be any string representing a person, whether it's a first name, full name, nickname, or even a codename (e.g., 'Agent X'). It's used primarily for display purposes, logging, or greeting messages and is not required to be unique or validated unless specified by the caller.",
414
+ },
415
+ ]}
416
+ returns="The return value. True for success, False otherwise."
417
+ raises={["ValueError: If somebody2 is equal to somebody."]}
418
+ style="google"
419
+ />
420
+ );
421
+ const res = toSourceText(
422
+ [
423
+ <py.FunctionDeclaration name="some_function" doc={doc}>
424
+ <py.StatementList>
425
+ <py.VariableDeclaration name="just_name" />
426
+ <py.VariableDeclaration name="name_and_type" type="number" />
427
+ <py.VariableDeclaration
428
+ name="name_type_and_value"
429
+ type="number"
430
+ initializer={12}
431
+ />
432
+ </py.StatementList>
433
+ </py.FunctionDeclaration>,
434
+ ],
435
+ { printOptions: { printWidth: 80, tabWidth: 4 } },
436
+ );
437
+
438
+ expect(res).toRenderTo(
439
+ d`
440
+ def some_function():
441
+ """
442
+ This is an example of a long docstring that will be broken in lines. We will
443
+ also render another paragraph after this one.
444
+
445
+ >> print("Hello world!")
446
+ >> x = "Hello"
447
+ >> print(x)
448
+
449
+ Args:
450
+ somebody (str, optional): Somebody's name. This can be any string
451
+ representing a person, whether it's a first name, full name,
452
+ nickname, or even a codename (e.g., 'Agent X'). It's used primarily
453
+ for display purposes, logging, or greeting messages and is not
454
+ required to be unique or validated unless specified by the caller.
455
+ Defaults to \"John Doe\".
456
+
457
+ somebody2 (str): Somebody's name. This can be any string representing a
458
+ person, whether it's a first name, full name, nickname, or even a
459
+ codename (e.g., 'Agent X'). It's used primarily for display
460
+ purposes, logging, or greeting messages and is not required to be
461
+ unique or validated unless specified by the caller.
462
+
463
+ Returns:
464
+ The return value. True for success, False otherwise.
465
+
466
+ Raises:
467
+ ValueError: If somebody2 is equal to somebody.
468
+ """
469
+ just_name = None
470
+ name_and_type: number = None
471
+ name_type_and_value: number = 12
472
+
473
+
474
+ `,
475
+ );
476
+ });
477
+
478
+ it("renders correctly in a Variable", () => {
479
+ const res = toSourceText(
480
+ [
481
+ <py.VariableDeclaration
482
+ name="myVar"
483
+ initializer={42}
484
+ doc="This is a very long docstring that will be broken in two lines when rendered. This part of the docstring will be in the second line."
485
+ />,
486
+ ],
487
+ { printOptions: { printWidth: 80, tabWidth: 4 } },
488
+ );
489
+
490
+ expect(res).toRenderTo(
491
+ d`
492
+ # This is a very long docstring that will be broken in two lines when rendered.
493
+ # This part of the docstring will be in the second line.
494
+ my_var = 42
495
+ `,
496
+ );
497
+ });
498
+
499
+ it("classic enum with explicit values", () => {
500
+ const result = toSourceText(
501
+ [
502
+ <py.EnumDeclaration
503
+ name="Color"
504
+ baseType="IntEnum"
505
+ members={[
506
+ { name: "RED", value: "1", doc: "The color red." },
507
+ { name: "GREEN", value: "2", doc: "The color green." },
508
+ { name: "BLUE", value: "3", doc: "The color blue." },
509
+ ]}
510
+ doc="An enum representing colors."
511
+ />,
512
+ ],
513
+ { externals: [enumModule] },
514
+ );
515
+ const expected = d`
516
+ from enum import IntEnum
517
+
518
+ # An enum representing colors.
519
+ class Color(IntEnum):
520
+ RED = 1 # The color red.
521
+ GREEN = 2 # The color green.
522
+ BLUE = 3 # The color blue.
523
+
524
+
525
+ `;
526
+ expect(result).toRenderTo(expected);
527
+ });
528
+ });
@@ -0,0 +1,36 @@
1
+ import { refkey } from "@alloy-js/core";
2
+ import { describe, it } from "vitest";
3
+ import * as py from "../src/index.js";
4
+ import { assertFileContents, toSourceTextMultiple } from "./utils.jsx";
5
+
6
+ describe("Reference", () => {
7
+ it("Verifies that a reference is correctly resolved", () => {
8
+ const rk1 = refkey();
9
+ const res = toSourceTextMultiple([
10
+ <py.SourceFile path="models.py">
11
+ <py.ClassDeclaration name="User" refkey={rk1} />
12
+ </py.SourceFile>,
13
+ <py.SourceFile path="services.py">
14
+ <py.VariableDeclaration
15
+ name="current_user"
16
+ type={<py.Reference refkey={rk1} />}
17
+ initializer={
18
+ <py.ClassInstantiation target="User" args={['"Marvin"']} />
19
+ }
20
+ />
21
+ </py.SourceFile>,
22
+ ]);
23
+ assertFileContents(res, {
24
+ "models.py": `
25
+ class User:
26
+ pass
27
+
28
+ `,
29
+ "services.py": `
30
+ from models import User
31
+
32
+ current_user: User = User("Marvin")
33
+ `,
34
+ });
35
+ });
36
+ });