@alloy-js/python 0.2.0-dev.2 → 0.2.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 (209) hide show
  1. package/dist/src/builtins/python.d.ts +3 -0
  2. package/dist/src/builtins/python.d.ts.map +1 -1
  3. package/dist/src/builtins/python.js +6 -0
  4. package/dist/src/builtins/python.js.map +1 -1
  5. package/dist/src/components/CallSignature.d.ts +4 -15
  6. package/dist/src/components/CallSignature.d.ts.map +1 -1
  7. package/dist/src/components/CallSignature.js +13 -67
  8. package/dist/src/components/CallSignature.js.map +1 -1
  9. package/dist/src/components/ClassMethodDeclaration.d.ts +22 -0
  10. package/dist/src/components/ClassMethodDeclaration.d.ts.map +1 -0
  11. package/dist/src/components/ClassMethodDeclaration.js +32 -0
  12. package/dist/src/components/ClassMethodDeclaration.js.map +1 -0
  13. package/dist/src/components/ConstructorDeclaration.d.ts +21 -0
  14. package/dist/src/components/ConstructorDeclaration.d.ts.map +1 -0
  15. package/dist/src/components/ConstructorDeclaration.js +35 -0
  16. package/dist/src/components/ConstructorDeclaration.js.map +1 -0
  17. package/dist/src/components/DunderMethodDeclaration.d.ts +21 -0
  18. package/dist/src/components/DunderMethodDeclaration.d.ts.map +1 -0
  19. package/dist/src/components/DunderMethodDeclaration.js +29 -0
  20. package/dist/src/components/DunderMethodDeclaration.js.map +1 -0
  21. package/dist/src/components/EnumDeclaration.d.ts +11 -32
  22. package/dist/src/components/EnumDeclaration.d.ts.map +1 -1
  23. package/dist/src/components/EnumDeclaration.js +10 -48
  24. package/dist/src/components/EnumDeclaration.js.map +1 -1
  25. package/dist/src/components/EnumMember.js +3 -3
  26. package/dist/src/components/EnumMember.js.map +1 -1
  27. package/dist/src/components/FunctionBase.d.ts +48 -0
  28. package/dist/src/components/FunctionBase.d.ts.map +1 -0
  29. package/dist/src/components/FunctionBase.js +91 -0
  30. package/dist/src/components/FunctionBase.js.map +1 -0
  31. package/dist/src/components/FunctionDeclaration.d.ts +11 -31
  32. package/dist/src/components/FunctionDeclaration.d.ts.map +1 -1
  33. package/dist/src/components/FunctionDeclaration.js +22 -79
  34. package/dist/src/components/FunctionDeclaration.js.map +1 -1
  35. package/dist/src/components/MemberExpression.d.ts.map +1 -1
  36. package/dist/src/components/MemberExpression.js +12 -13
  37. package/dist/src/components/MemberExpression.js.map +1 -1
  38. package/dist/src/components/MethodBase.d.ts +29 -0
  39. package/dist/src/components/MethodBase.d.ts.map +1 -0
  40. package/dist/src/components/MethodBase.js +32 -0
  41. package/dist/src/components/MethodBase.js.map +1 -0
  42. package/dist/src/components/MethodDeclaration.d.ts +22 -0
  43. package/dist/src/components/MethodDeclaration.d.ts.map +1 -0
  44. package/dist/src/components/MethodDeclaration.js +34 -0
  45. package/dist/src/components/MethodDeclaration.js.map +1 -0
  46. package/dist/src/components/PropertyDeclaration.d.ts +71 -0
  47. package/dist/src/components/PropertyDeclaration.d.ts.map +1 -0
  48. package/dist/src/components/PropertyDeclaration.js +227 -0
  49. package/dist/src/components/PropertyDeclaration.js.map +1 -0
  50. package/dist/src/components/PyDoc.d.ts +107 -42
  51. package/dist/src/components/PyDoc.d.ts.map +1 -1
  52. package/dist/src/components/PyDoc.js +845 -181
  53. package/dist/src/components/PyDoc.js.map +1 -1
  54. package/dist/src/components/SourceFile.d.ts +24 -0
  55. package/dist/src/components/SourceFile.d.ts.map +1 -1
  56. package/dist/src/components/SourceFile.js +28 -1
  57. package/dist/src/components/SourceFile.js.map +1 -1
  58. package/dist/src/components/StaticMethodDeclaration.d.ts +22 -0
  59. package/dist/src/components/StaticMethodDeclaration.d.ts.map +1 -0
  60. package/dist/src/components/StaticMethodDeclaration.js +32 -0
  61. package/dist/src/components/StaticMethodDeclaration.js.map +1 -0
  62. package/dist/src/components/TypeArguments.d.ts +9 -0
  63. package/dist/src/components/TypeArguments.d.ts.map +1 -0
  64. package/dist/src/components/TypeArguments.js +18 -0
  65. package/dist/src/components/TypeArguments.js.map +1 -0
  66. package/dist/src/components/TypeReference.d.ts +14 -0
  67. package/dist/src/components/TypeReference.d.ts.map +1 -0
  68. package/dist/src/components/TypeReference.js +29 -0
  69. package/dist/src/components/TypeReference.js.map +1 -0
  70. package/dist/src/components/UnionTypeExpression.d.ts +1 -2
  71. package/dist/src/components/UnionTypeExpression.d.ts.map +1 -1
  72. package/dist/src/components/UnionTypeExpression.js +3 -11
  73. package/dist/src/components/UnionTypeExpression.js.map +1 -1
  74. package/dist/src/components/VariableDeclaration.d.ts.map +1 -1
  75. package/dist/src/components/VariableDeclaration.js +3 -3
  76. package/dist/src/components/VariableDeclaration.js.map +1 -1
  77. package/dist/src/components/index.d.ts +10 -0
  78. package/dist/src/components/index.d.ts.map +1 -1
  79. package/dist/src/components/index.js +9 -0
  80. package/dist/src/components/index.js.map +1 -1
  81. package/dist/src/parameter-descriptor.d.ts +1 -4
  82. package/dist/src/parameter-descriptor.d.ts.map +1 -1
  83. package/dist/src/parameter-descriptor.js +7 -1
  84. package/dist/src/parameter-descriptor.js.map +1 -1
  85. package/dist/src/symbol-creation.d.ts +4 -0
  86. package/dist/src/symbol-creation.d.ts.map +1 -1
  87. package/dist/src/symbol-creation.js +12 -0
  88. package/dist/src/symbol-creation.js.map +1 -1
  89. package/dist/src/symbols/factories.d.ts +15 -0
  90. package/dist/src/symbols/factories.d.ts.map +1 -0
  91. package/dist/src/symbols/factories.js +28 -0
  92. package/dist/src/symbols/factories.js.map +1 -0
  93. package/dist/src/symbols/index.d.ts +1 -0
  94. package/dist/src/symbols/index.d.ts.map +1 -1
  95. package/dist/src/symbols/index.js +1 -0
  96. package/dist/src/symbols/index.js.map +1 -1
  97. package/dist/src/symbols/reference.d.ts +1 -1
  98. package/dist/src/symbols/reference.d.ts.map +1 -1
  99. package/dist/src/symbols/reference.js +1 -1
  100. package/dist/src/symbols/reference.js.map +1 -1
  101. package/dist/src/utils.d.ts.map +1 -1
  102. package/dist/src/utils.js +1 -1
  103. package/dist/src/utils.js.map +1 -1
  104. package/dist/test/callsignatures.test.js +42 -64
  105. package/dist/test/callsignatures.test.js.map +1 -1
  106. package/dist/test/class-method-declaration.test.d.ts +2 -0
  107. package/dist/test/class-method-declaration.test.d.ts.map +1 -0
  108. package/dist/test/class-method-declaration.test.js +61 -0
  109. package/dist/test/class-method-declaration.test.js.map +1 -0
  110. package/dist/test/classdeclarations.test.js +6 -8
  111. package/dist/test/classdeclarations.test.js.map +1 -1
  112. package/dist/test/constructordeclaration.test.d.ts +2 -0
  113. package/dist/test/constructordeclaration.test.d.ts.map +1 -0
  114. package/dist/test/constructordeclaration.test.js +58 -0
  115. package/dist/test/constructordeclaration.test.js.map +1 -0
  116. package/dist/test/dundermethoddeclaration.test.d.ts +2 -0
  117. package/dist/test/dundermethoddeclaration.test.d.ts.map +1 -0
  118. package/dist/test/dundermethoddeclaration.test.js +65 -0
  119. package/dist/test/dundermethoddeclaration.test.js.map +1 -0
  120. package/dist/test/enums.test.js +14 -16
  121. package/dist/test/enums.test.js.map +1 -1
  122. package/dist/test/externals.test.js +2 -4
  123. package/dist/test/externals.test.js.map +1 -1
  124. package/dist/test/factories.test.d.ts +2 -0
  125. package/dist/test/factories.test.d.ts.map +1 -0
  126. package/dist/test/factories.test.js +78 -0
  127. package/dist/test/factories.test.js.map +1 -0
  128. package/dist/test/functiondeclaration.test.js +213 -59
  129. package/dist/test/functiondeclaration.test.js.map +1 -1
  130. package/dist/test/memberexpressions.test.js +1 -1
  131. package/dist/test/memberexpressions.test.js.map +1 -1
  132. package/dist/test/methoddeclaration.test.d.ts +2 -0
  133. package/dist/test/methoddeclaration.test.d.ts.map +1 -0
  134. package/dist/test/methoddeclaration.test.js +239 -0
  135. package/dist/test/methoddeclaration.test.js.map +1 -0
  136. package/dist/test/namepolicies.test.js +1 -2
  137. package/dist/test/namepolicies.test.js.map +1 -1
  138. package/dist/test/propertydeclaration.test.d.ts +2 -0
  139. package/dist/test/propertydeclaration.test.d.ts.map +1 -0
  140. package/dist/test/propertydeclaration.test.js +229 -0
  141. package/dist/test/propertydeclaration.test.js.map +1 -0
  142. package/dist/test/pydocs.test.js +926 -126
  143. package/dist/test/pydocs.test.js.map +1 -1
  144. package/dist/test/references.test.js +1 -5
  145. package/dist/test/references.test.js.map +1 -1
  146. package/dist/test/sourcefiles.test.js +90 -1
  147. package/dist/test/sourcefiles.test.js.map +1 -1
  148. package/dist/test/staticmethoddeclaration.test.d.ts +2 -0
  149. package/dist/test/staticmethoddeclaration.test.d.ts.map +1 -0
  150. package/dist/test/staticmethoddeclaration.test.js +61 -0
  151. package/dist/test/staticmethoddeclaration.test.js.map +1 -0
  152. package/dist/test/typereference.test.d.ts +2 -0
  153. package/dist/test/typereference.test.d.ts.map +1 -0
  154. package/dist/test/typereference.test.js +51 -0
  155. package/dist/test/typereference.test.js.map +1 -0
  156. package/dist/test/uniontypeexpression.test.js +152 -15
  157. package/dist/test/uniontypeexpression.test.js.map +1 -1
  158. package/dist/test/variables.test.js +28 -19
  159. package/dist/test/variables.test.js.map +1 -1
  160. package/dist/tsconfig.tsbuildinfo +1 -1
  161. package/package.json +2 -2
  162. package/src/builtins/python.ts +7 -0
  163. package/src/components/CallSignature.tsx +17 -69
  164. package/src/components/ClassMethodDeclaration.tsx +34 -0
  165. package/src/components/ConstructorDeclaration.tsx +37 -0
  166. package/src/components/DunderMethodDeclaration.tsx +30 -0
  167. package/src/components/EnumDeclaration.tsx +16 -44
  168. package/src/components/EnumMember.tsx +3 -3
  169. package/src/components/FunctionBase.tsx +88 -0
  170. package/src/components/FunctionDeclaration.tsx +18 -82
  171. package/src/components/MemberExpression.tsx +6 -19
  172. package/src/components/MethodBase.tsx +53 -0
  173. package/src/components/MethodDeclaration.tsx +27 -0
  174. package/src/components/PropertyDeclaration.tsx +264 -0
  175. package/src/components/PyDoc.tsx +795 -195
  176. package/src/components/SourceFile.tsx +29 -0
  177. package/src/components/StaticMethodDeclaration.tsx +34 -0
  178. package/src/components/TypeArguments.tsx +24 -0
  179. package/src/components/TypeReference.tsx +33 -0
  180. package/src/components/UnionTypeExpression.tsx +4 -15
  181. package/src/components/VariableDeclaration.tsx +1 -3
  182. package/src/components/index.ts +10 -0
  183. package/src/parameter-descriptor.ts +6 -5
  184. package/src/symbol-creation.ts +17 -0
  185. package/src/symbols/factories.ts +39 -0
  186. package/src/symbols/index.ts +1 -0
  187. package/src/symbols/reference.tsx +3 -5
  188. package/src/utils.ts +0 -2
  189. package/temp/api.json +5281 -2273
  190. package/test/callsignatures.test.tsx +102 -74
  191. package/test/class-method-declaration.test.tsx +53 -0
  192. package/test/classdeclarations.test.tsx +7 -9
  193. package/test/constructordeclaration.test.tsx +48 -0
  194. package/test/dundermethoddeclaration.test.tsx +53 -0
  195. package/test/enums.test.tsx +14 -16
  196. package/test/externals.test.tsx +5 -7
  197. package/test/factories.test.tsx +72 -0
  198. package/test/functiondeclaration.test.tsx +196 -44
  199. package/test/memberexpressions.test.tsx +7 -2
  200. package/test/methoddeclaration.test.tsx +202 -0
  201. package/test/namepolicies.test.tsx +1 -2
  202. package/test/propertydeclaration.test.tsx +192 -0
  203. package/test/pydocs.test.tsx +1093 -129
  204. package/test/references.test.tsx +1 -1
  205. package/test/sourcefiles.test.tsx +100 -1
  206. package/test/staticmethoddeclaration.test.tsx +49 -0
  207. package/test/typereference.test.tsx +52 -0
  208. package/test/uniontypeexpression.test.tsx +169 -34
  209. package/test/variables.test.tsx +27 -16
@@ -4,7 +4,7 @@ import { d } from "@alloy-js/core/testing";
4
4
  import { describe, expect, it } from "vitest";
5
5
  import { enumModule } from "../src/builtins/python.js";
6
6
  import * as py from "../src/index.js";
7
- import { toSourceText } from "./utils.js";
7
+ import { assertFileContents, toSourceText, toSourceTextMultiple } from "./utils.js";
8
8
  describe("PyDoc", () => {
9
9
  it("formats properly", () => {
10
10
  const res = toSourceText([_$createComponent(py.PyDoc, {
@@ -120,161 +120,645 @@ describe("PyDocExample", () => {
120
120
  `);
121
121
  });
122
122
  });
123
- describe("GoogleStyleDocParam", () => {
124
- it("name only", () => {
125
- const res = toSourceText([_$createComponent(py.PyDoc, {
123
+ describe("SimpleCommentBlock", () => {
124
+ it("renders simple comment block", () => {
125
+ const res = toSourceText([_$createComponent(py.SimpleCommentBlock, {
126
+ children: "This is a simple comment block that spans multiple lines."
127
+ })]);
128
+ expect(res).toRenderTo(d`
129
+ # This is a simple comment block that spans multiple lines.
130
+
131
+ `);
132
+ });
133
+ it("renders comment block with line breaks", () => {
134
+ const res = toSourceText([_$createComponent(py.SimpleCommentBlock, {
126
135
  get children() {
127
- return _$createComponent(py.GoogleStyleDocParam, {
128
- name: "somebody"
129
- });
136
+ return ["First line of comment.", _$createIntrinsic("br", {}), "Second line of comment."];
130
137
  }
131
138
  })]);
132
139
  expect(res).toRenderTo(d`
133
- """
134
- somebody
135
- """
140
+ # First line of comment. Second line of comment.
141
+
142
+ `);
143
+ });
144
+ });
145
+ describe("SimpleInlineComment", () => {
146
+ it("renders inline comment", () => {
147
+ const res = toSourceText([["x = 42", _$createComponent(py.SimpleInlineComment, {
148
+ children: "This is an inline comment"
149
+ })]]);
150
+ expect(res).toRenderTo(d`
151
+ x = 42 # This is an inline comment
152
+ `);
153
+ });
154
+ it("renders inline comment with complex text", () => {
155
+ const res = toSourceText([["result = calculate()", _$createComponent(py.SimpleInlineComment, {
156
+ children: "TODO: Add error handling here"
157
+ })]]);
158
+ expect(res).toRenderTo(d`
159
+ result = calculate() # TODO: Add error handling here
160
+ `);
161
+ });
162
+ });
163
+ describe("SimpleInlineMemberComment", () => {
164
+ it("renders inline member comment", () => {
165
+ const res = toSourceText([["status: int", _$createComponent(py.SimpleInlineMemberComment, {
166
+ children: "HTTP status code"
167
+ })]]);
168
+ expect(res).toRenderTo(d`
169
+ status: int #: HTTP status code
170
+ `);
171
+ });
172
+ it("renders inline member comment for variable declaration", () => {
173
+ const res = toSourceText([["max_retries = 3", _$createComponent(py.SimpleInlineMemberComment, {
174
+ children: "Maximum number of retry attempts"
175
+ })]]);
176
+ expect(res).toRenderTo(d`
177
+ max_retries = 3 #: Maximum number of retry attempts
178
+ `);
179
+ });
180
+ });
181
+ describe("New Documentation Components", () => {
182
+ it("ModuleDoc renders correctly", () => {
183
+ const res = toSourceText([_$createComponent(py.ModuleDoc, {
184
+ get description() {
185
+ return [_$createComponent(Prose, {
186
+ children: "This module demonstrates documentation as specified by the Google Python Style Guide."
187
+ })];
188
+ },
189
+ attributes: [{
190
+ name: "module_level_variable1",
191
+ type: "int",
192
+ children: "Module level variables may be documented."
193
+ }],
194
+ get examples() {
195
+ return [_$createComponent(py.PyDocExample, {
196
+ children: "print(\"mod\")"
197
+ })];
198
+ },
199
+ seeAlso: ["another_module.func", "RelatedClass"],
200
+ warning: "Internal API.",
201
+ deprecated: "Use new_module instead.",
202
+ todo: ["For module TODOs", "You have to also use sphinx.ext.todo extension"]
203
+ })]);
204
+ expect(res).toRenderTo(d`
205
+ """
206
+ This module demonstrates documentation as specified by the Google Python Style
207
+ Guide.
136
208
 
209
+ Attributes:
210
+ module_level_variable1 (int): Module level variables may be documented.
137
211
 
138
- `);
212
+ Examples:
213
+ >> print("mod")
214
+
215
+ See Also:
216
+ another_module.func
217
+ RelatedClass
218
+
219
+ Warning:
220
+ Internal API.
221
+
222
+ Deprecated:
223
+ Use new_module instead.
224
+
225
+ Todo:
226
+ * For module TODOs
227
+ * You have to also use sphinx.ext.todo extension
228
+ """
229
+
230
+
231
+ `);
139
232
  });
140
- it("name and type", () => {
141
- const res = toSourceText([_$createComponent(py.PyDoc, {
142
- get children() {
143
- return _$createComponent(py.GoogleStyleDocParam, {
144
- name: "somebody",
145
- type: "str"
146
- });
147
- }
233
+ it("PropertyDoc renders correctly", () => {
234
+ const res = toSourceText([_$createComponent(py.PropertyDoc, {
235
+ get description() {
236
+ return [_$createComponent(Prose, {
237
+ children: "Properties should be documented in their getter method."
238
+ })];
239
+ },
240
+ returns: "str: The readonly property value.",
241
+ get examples() {
242
+ return [_$createComponent(py.PyDocExample, {
243
+ children: "print(obj.name)"
244
+ })];
245
+ },
246
+ seeAlso: ["other_property"],
247
+ warning: "Access may be slow.",
248
+ deprecated: "Use full_name instead.",
249
+ note: "If the setter method contains notable behavior, it should be mentioned here."
148
250
  })]);
149
251
  expect(res).toRenderTo(d`
150
- """
151
- somebody (str)
152
- """
252
+ """
253
+ Properties should be documented in their getter method.
153
254
 
255
+ Returns:
256
+ str: The readonly property value.
154
257
 
155
- `);
258
+ Examples:
259
+ >> print(obj.name)
260
+
261
+ See Also:
262
+ other_property
263
+
264
+ Warning:
265
+ Access may be slow.
266
+
267
+ Deprecated:
268
+ Use full_name instead.
269
+
270
+ Note:
271
+ If the setter method contains notable behavior, it should be mentioned here.
272
+ """
273
+
274
+
275
+ `);
156
276
  });
157
- it("name, type and description", () => {
158
- const res = toSourceText([_$createComponent(py.PyDoc, {
159
- get children() {
160
- return _$createComponent(py.GoogleStyleDocParam, {
161
- name: "somebody",
162
- type: "str",
163
- children: "Somebody's name."
164
- });
165
- }
277
+ it("GeneratorDoc renders correctly", () => {
278
+ const res = toSourceText([_$createComponent(py.GeneratorDoc, {
279
+ get description() {
280
+ return [_$createComponent(Prose, {
281
+ children: "Generators have a Yields section instead of a Returns section."
282
+ })];
283
+ },
284
+ parameters: [{
285
+ name: "n",
286
+ type: "int",
287
+ doc: "The upper limit of the range to generate, from 0 to n - 1."
288
+ }],
289
+ yields: "int: The next number in the range of 0 to n - 1.",
290
+ get examples() {
291
+ return [_$createComponent(py.PyDocExample, {
292
+ children: "print(next(gen))"
293
+ })];
294
+ },
295
+ seeAlso: ["make_generator"],
296
+ warning: "Do not consume in tight loops without sleep.",
297
+ deprecated: "Use new_generator instead.",
298
+ note: "Examples should be written in doctest format."
166
299
  })]);
167
300
  expect(res).toRenderTo(d`
168
- """
169
- somebody (str): Somebody's name.
170
- """
301
+ """
302
+ Generators have a Yields section instead of a Returns section.
171
303
 
304
+ Args:
305
+ n (int): The upper limit of the range to generate, from 0 to n - 1.
172
306
 
173
- `);
307
+ Yields:
308
+ int: The next number in the range of 0 to n - 1.
309
+
310
+ Examples:
311
+ >> print(next(gen))
312
+
313
+ See Also:
314
+ make_generator
315
+
316
+ Warning:
317
+ Do not consume in tight loops without sleep.
318
+
319
+ Deprecated:
320
+ Use new_generator instead.
321
+
322
+ Note:
323
+ Examples should be written in doctest format.
324
+ """
325
+
326
+
327
+ `);
174
328
  });
175
- it("name, type, description, and optional", () => {
176
- const res = toSourceText([_$createComponent(py.PyDoc, {
177
- get children() {
178
- return _$createComponent(py.GoogleStyleDocParam, {
179
- name: "somebody",
180
- type: "str",
181
- optional: true,
182
- children: "Somebody's name."
183
- });
184
- }
329
+ it("ExceptionDoc renders correctly", () => {
330
+ const res = toSourceText([_$createComponent(py.ExceptionDoc, {
331
+ get description() {
332
+ return [_$createComponent(Prose, {
333
+ children: "Exceptions are documented in the same way as classes."
334
+ })];
335
+ },
336
+ parameters: [{
337
+ name: "msg",
338
+ type: "str",
339
+ doc: "Human readable string describing the exception."
340
+ }, {
341
+ name: "code",
342
+ type: "int",
343
+ default: undefined,
344
+ doc: "Error code."
345
+ }],
346
+ attributes: [{
347
+ name: "msg",
348
+ type: "str",
349
+ children: "Human readable string describing the exception."
350
+ }, {
351
+ name: "code",
352
+ type: "int",
353
+ children: "Exception error code."
354
+ }],
355
+ seeAlso: ["BaseException"],
356
+ deprecated: "Use NewException instead.",
357
+ note: "Do not include the 'self' parameter in the Args section."
185
358
  })]);
186
359
  expect(res).toRenderTo(d`
187
- """
188
- somebody (str, optional): Somebody's name.
189
- """
360
+ """
361
+ Exceptions are documented in the same way as classes.
190
362
 
363
+ Args:
364
+ msg (str): Human readable string describing the exception.
191
365
 
192
- `);
366
+ code (int): Error code.
367
+
368
+ Attributes:
369
+ msg (str): Human readable string describing the exception.
370
+
371
+ code (int): Exception error code.
372
+
373
+ See Also:
374
+ BaseException
375
+
376
+ Deprecated:
377
+ Use NewException instead.
378
+
379
+ Note:
380
+ Do not include the 'self' parameter in the Args section.
381
+ """
382
+
383
+
384
+ `);
193
385
  });
194
- it("name, type, description, and optional with default value", () => {
195
- const res = toSourceText([_$createComponent(py.PyDoc, {
196
- get children() {
197
- return _$createComponent(py.GoogleStyleDocParam, {
198
- name: "somebody",
199
- type: "str",
200
- optional: true,
201
- defaultValue: "John Doe",
202
- children: "Somebody's name."
203
- });
204
- }
386
+ it("MethodDoc renders correctly without default note", () => {
387
+ const res = toSourceText([_$createComponent(py.MethodDoc, {
388
+ get description() {
389
+ return [_$createComponent(Prose, {
390
+ children: "Class methods are similar to regular functions."
391
+ })];
392
+ },
393
+ parameters: [{
394
+ name: "param1",
395
+ doc: "The first parameter."
396
+ }, {
397
+ name: "param2",
398
+ doc: "The second parameter."
399
+ }],
400
+ returns: "True if successful, False otherwise.",
401
+ overrides: "Base.method"
205
402
  })]);
206
403
  expect(res).toRenderTo(d`
207
404
  """
208
- somebody (str, optional): Somebody's name. Defaults to \"John Doe\".
405
+ Class methods are similar to regular functions.
406
+
407
+ Args:
408
+ param1: The first parameter.
409
+
410
+ param2: The second parameter.
411
+
412
+ Returns:
413
+ True if successful, False otherwise.
414
+
415
+ Overrides:
416
+ Base.method
209
417
  """
210
418
 
211
419
 
212
420
  `);
213
421
  });
214
- it("name, type, description, and optional with default value with a very long description", () => {
215
- const res = toSourceText([_$createComponent(py.PyDoc, {
216
- get children() {
217
- return [_$createComponent(py.GoogleStyleDocParam, {
218
- name: "somebody",
219
- type: "str",
220
- optional: true,
221
- defaultValue: "John Doe",
222
- children: "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."
223
- }), _$createComponent(py.GoogleStyleDocParam, {
224
- name: "somebody2",
225
- type: "str",
226
- children: "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."
422
+ it("MethodDoc renders correctly with custom note", () => {
423
+ const res = toSourceText([_$createComponent(py.MethodDoc, {
424
+ get description() {
425
+ return [_$createComponent(Prose, {
426
+ children: "Class methods are similar to regular functions."
427
+ })];
428
+ },
429
+ parameters: [{
430
+ name: "param1",
431
+ doc: "The first parameter."
432
+ }],
433
+ returns: "True if successful, False otherwise.",
434
+ note: "This method has special behavior when called multiple times."
435
+ })]);
436
+ expect(res).toRenderTo(d`
437
+ """
438
+ Class methods are similar to regular functions.
439
+
440
+ Args:
441
+ param1: The first parameter.
442
+
443
+ Returns:
444
+ True if successful, False otherwise.
445
+
446
+ Note:
447
+ This method has special behavior when called multiple times.
448
+ """
449
+
450
+
451
+ `);
452
+ });
453
+ it("ModuleDoc with minimal content", () => {
454
+ const res = toSourceText([_$createComponent(py.ModuleDoc, {
455
+ get description() {
456
+ return [_$createComponent(Prose, {
457
+ children: "Simple module description."
227
458
  })];
228
459
  }
229
- })], {
230
- printOptions: {
231
- printWidth: 80
460
+ })]);
461
+ expect(res).toRenderTo(d`
462
+ """
463
+ Simple module description.
464
+ """
465
+
466
+
467
+ `);
468
+ });
469
+ it("ModuleDoc with only todo items", () => {
470
+ const res = toSourceText([_$createComponent(py.ModuleDoc, {
471
+ get description() {
472
+ return [_$createComponent(Prose, {
473
+ children: "Module with pending tasks."
474
+ })];
475
+ },
476
+ todo: ["Implement feature X", "Add more tests", "Update documentation"]
477
+ })]);
478
+ expect(res).toRenderTo(d`
479
+ """
480
+ Module with pending tasks.
481
+
482
+ Todo:
483
+ * Implement feature X
484
+ * Add more tests
485
+ * Update documentation
486
+ """
487
+
488
+
489
+ `);
490
+ });
491
+ it("PropertyDoc minimal (description only)", () => {
492
+ const res = toSourceText([_$createComponent(py.PropertyDoc, {
493
+ get description() {
494
+ return [_$createComponent(Prose, {
495
+ children: "A simple readonly property."
496
+ })];
232
497
  }
233
- });
498
+ })]);
234
499
  expect(res).toRenderTo(d`
235
- """
236
- somebody (str, optional): Somebody's name. This can be any string representing a
237
- person, whether it's a first name, full name, nickname, or even a codename
238
- (e.g., "Agent X"). It's used primarily for display purposes, logging, or
239
- greeting messages and is not required to be unique or validated unless
240
- specified by the caller. Defaults to \"John Doe\".
241
-
242
- somebody2 (str): Somebody's name. This can be any string representing a person,
243
- whether it's a first name, full name, nickname, or even a codename (e.g.,
244
- "Agent X"). It's used primarily for display purposes, logging, or greeting
245
- messages and is not required to be unique or validated unless specified by
246
- the caller.
247
- """
500
+ """
501
+ A simple readonly property.
502
+ """
248
503
 
249
504
 
250
- `);
505
+ `);
506
+ });
507
+ it("PropertyDoc with getter and setter info", () => {
508
+ const res = toSourceText([_$createComponent(py.PropertyDoc, {
509
+ get description() {
510
+ return [_$createComponent(Prose, {
511
+ children: "Properties with both a getter and setter should only be documented in their getter method."
512
+ })];
513
+ },
514
+ returns: ":obj:`list` of :obj:`str`: The property value.",
515
+ note: "If the setter method contains notable behavior, it should be mentioned here."
516
+ })]);
517
+ expect(res).toRenderTo(d`
518
+ """
519
+ Properties with both a getter and setter should only be documented in their
520
+ getter method.
521
+
522
+ Returns:
523
+ :obj:\`list\` of :obj:\`str\`: The property value.
524
+
525
+ Note:
526
+ If the setter method contains notable behavior, it should be mentioned here.
527
+ """
528
+
529
+
530
+ `);
531
+ });
532
+ it("GeneratorDoc with complex parameters", () => {
533
+ const res = toSourceText([_$createComponent(py.GeneratorDoc, {
534
+ get description() {
535
+ return [_$createComponent(Prose, {
536
+ children: "A more complex generator example with multiple parameters."
537
+ })];
538
+ },
539
+ parameters: [{
540
+ name: "start",
541
+ type: "int",
542
+ default: "0",
543
+ doc: "Starting value for the sequence."
544
+ }, {
545
+ name: "stop",
546
+ type: "int",
547
+ doc: "Ending value for the sequence (exclusive)."
548
+ }, {
549
+ name: "step",
550
+ type: "int",
551
+ default: "1",
552
+ doc: "Step size between values."
553
+ }],
554
+ yields: "int: The next number in the sequence.",
555
+ raises: ["ValueError: If step is zero.", "TypeError: If parameters are not integers."]
556
+ })]);
557
+ expect(res).toRenderTo(d`
558
+ """
559
+ A more complex generator example with multiple parameters.
560
+
561
+ Args:
562
+ start (int, optional): Starting value for the sequence. Defaults to "0".
563
+
564
+ stop (int): Ending value for the sequence (exclusive).
565
+
566
+ step (int, optional): Step size between values. Defaults to "1".
567
+
568
+ Yields:
569
+ int: The next number in the sequence.
570
+
571
+ Raises:
572
+ ValueError: If step is zero.
573
+
574
+ Raises:
575
+ TypeError: If parameters are not integers.
576
+ """
577
+
578
+
579
+ `);
580
+ });
581
+ it("ExceptionDoc with comprehensive documentation", () => {
582
+ const res = toSourceText([_$createComponent(py.ExceptionDoc, {
583
+ get description() {
584
+ return [_$createComponent(Prose, {
585
+ children: "A custom exception for authentication failures."
586
+ }), _$createComponent(Prose, {
587
+ children: "This exception is raised when authentication credentials are invalid or when authentication tokens have expired."
588
+ })];
589
+ },
590
+ parameters: [{
591
+ name: "message",
592
+ type: "str",
593
+ doc: "Human readable error message describing the authentication failure."
594
+ }, {
595
+ name: "error_code",
596
+ type: "int",
597
+ default: "401",
598
+ doc: "HTTP error code associated with the authentication failure."
599
+ }, {
600
+ name: "retry_after",
601
+ type: "int",
602
+ default: undefined,
603
+ doc: "Number of seconds to wait before retrying authentication."
604
+ }],
605
+ attributes: [{
606
+ name: "message",
607
+ type: "str",
608
+ children: "The error message."
609
+ }, {
610
+ name: "error_code",
611
+ type: "int",
612
+ children: "HTTP status code."
613
+ }, {
614
+ name: "retry_after",
615
+ type: "int",
616
+ children: "Retry delay in seconds, if applicable."
617
+ }],
618
+ note: "This exception should be caught and handled gracefully in production code."
619
+ })]);
620
+ expect(res).toRenderTo(d`
621
+ """
622
+ A custom exception for authentication failures.
623
+
624
+ This exception is raised when authentication credentials are invalid or when
625
+ authentication tokens have expired.
626
+
627
+ Args:
628
+ message (str): Human readable error message describing the authentication
629
+ failure.
630
+
631
+ error_code (int, optional): HTTP error code associated with the
632
+ authentication failure. Defaults to "401".
633
+
634
+ retry_after (int): Number of seconds to wait before retrying authentication.
635
+
636
+ Attributes:
637
+ message (str): The error message.
638
+
639
+ error_code (int): HTTP status code.
640
+
641
+ retry_after (int): Retry delay in seconds, if applicable.
642
+
643
+ Note:
644
+ This exception should be caught and handled gracefully in production code.
645
+ """
646
+
647
+
648
+ `);
649
+ });
650
+ it("MethodDoc with raises but no returns", () => {
651
+ const res = toSourceText([_$createComponent(py.MethodDoc, {
652
+ get description() {
653
+ return [_$createComponent(Prose, {
654
+ children: "A method that performs an action but doesn't return a value."
655
+ })];
656
+ },
657
+ parameters: [{
658
+ name: "data",
659
+ type: "bytes",
660
+ doc: "Raw data to process."
661
+ }],
662
+ raises: ["ValueError: If data is empty or invalid.", "IOError: If processing fails due to I/O issues."]
663
+ })]);
664
+ expect(res).toRenderTo(d`
665
+ """
666
+ A method that performs an action but doesn't return a value.
667
+
668
+ Args:
669
+ data (bytes): Raw data to process.
670
+
671
+ Raises:
672
+ ValueError: If data is empty or invalid.
673
+
674
+ Raises:
675
+ IOError: If processing fails due to I/O issues.
676
+ """
677
+
678
+
679
+ `);
680
+ });
681
+ it("MethodDoc with no parameters", () => {
682
+ const res = toSourceText([_$createComponent(py.MethodDoc, {
683
+ get description() {
684
+ return [_$createComponent(Prose, {
685
+ children: "A simple method with no parameters (except self)."
686
+ })];
687
+ },
688
+ returns: "bool: True if the operation was successful.",
689
+ note: "This is a parameterless method that only operates on instance state."
690
+ })]);
691
+ expect(res).toRenderTo(d`
692
+ """
693
+ A simple method with no parameters (except self).
694
+
695
+ Returns:
696
+ bool: True if the operation was successful.
697
+
698
+ Note:
699
+ This is a parameterless method that only operates on instance state.
700
+ """
701
+
702
+
703
+ `);
251
704
  });
252
- it("name, type, description, and optional with default value with a description containing a linebreak", () => {
705
+ it("AttributeDoc standalone usage", () => {
253
706
  const res = toSourceText([_$createComponent(py.PyDoc, {
254
707
  get children() {
255
- return _$createComponent(py.GoogleStyleDocParam, {
256
- name: "somebody",
257
- type: "str",
258
- optional: true,
259
- defaultValue: "John Doe",
260
- get children() {
261
- return ["Somebody's name. This is one line", _$createIntrinsic("hbr", {}), "This is another line."];
262
- }
708
+ return _$createComponent(py.AttributeDoc, {
709
+ name: "connection_timeout",
710
+ type: "float",
711
+ children: "Maximum time in seconds to wait for a connection to be established."
263
712
  });
264
713
  }
265
- })], {
266
- printOptions: {
267
- printWidth: 80
268
- }
269
- });
714
+ })]);
270
715
  expect(res).toRenderTo(d`
271
- """
272
- somebody (str, optional): Somebody's name. This is one line
273
- This is another line. Defaults to \"John Doe\".
274
- """
716
+ """
717
+ connection_timeout (float): Maximum time in seconds to wait for a connection to
718
+ be established.
719
+ """
275
720
 
276
721
 
277
- `);
722
+ `);
723
+ });
724
+ it("GeneratorDoc with examples in description", () => {
725
+ const res = toSourceText([_$createComponent(py.GeneratorDoc, {
726
+ get description() {
727
+ return [_$createComponent(Prose, {
728
+ children: "Generators have a Yields section instead of a Returns section."
729
+ }), _$createComponent(py.PyDocExample, {
730
+ get children() {
731
+ return ["print([i for i in example_generator(4)])", _$createIntrinsic("br", {}), "[0, 1, 2, 3]"];
732
+ }
733
+ })];
734
+ },
735
+ parameters: [{
736
+ name: "n",
737
+ type: "int",
738
+ doc: "The upper limit of the range to generate, from 0 to n - 1."
739
+ }],
740
+ yields: "int: The next number in the range of 0 to n - 1.",
741
+ note: "Examples should be written in doctest format, and should illustrate how to use the function."
742
+ })]);
743
+ expect(res).toRenderTo(d`
744
+ """
745
+ Generators have a Yields section instead of a Returns section.
746
+
747
+ >> print([i for i in example_generator(4)])
748
+ >> [0, 1, 2, 3]
749
+
750
+ Args:
751
+ n (int): The upper limit of the range to generate, from 0 to n - 1.
752
+
753
+ Yields:
754
+ int: The next number in the range of 0 to n - 1.
755
+
756
+ Note:
757
+ Examples should be written in doctest format, and should illustrate how to use the function.
758
+ """
759
+
760
+
761
+ `);
278
762
  });
279
763
  });
280
764
  describe("Full example", () => {
@@ -289,17 +773,34 @@ describe("Full example", () => {
289
773
  }
290
774
  })];
291
775
  },
776
+ attributes: [{
777
+ name: "attr1",
778
+ type: "str",
779
+ children: "Description of attr1."
780
+ }, {
781
+ name: "attr2",
782
+ type: "int",
783
+ children: "Description of attr2."
784
+ }],
785
+ get examples() {
786
+ return [_$createComponent(py.PyDocExample, {
787
+ children: "print(\"class-doc\")"
788
+ })];
789
+ },
790
+ seeAlso: ["RelatedClass", "helper_function"],
791
+ warning: "This class is experimental.",
792
+ deprecated: "Use NewClass instead.",
292
793
  parameters: [{
293
794
  name: "somebody",
294
795
  type: "str",
295
- optional: true,
296
796
  default: "John Doe",
297
- 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\"."
797
+ 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."
298
798
  }, {
299
799
  name: "somebody2",
300
800
  type: "str",
301
801
  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."
302
802
  }],
803
+ note: "Do not include the 'self' parameter in the Args section.",
303
804
  style: "google"
304
805
  });
305
806
  const res = toSourceText([_$createComponent(py.ClassDeclaration, {
@@ -312,10 +813,10 @@ describe("Full example", () => {
312
813
  name: "just_name"
313
814
  }), _$createComponent(py.VariableDeclaration, {
314
815
  name: "name_and_type",
315
- type: "number"
816
+ type: "int"
316
817
  }), _$createComponent(py.VariableDeclaration, {
317
818
  name: "name_type_and_value",
318
- type: "number",
819
+ type: "int",
319
820
  initializer: 12
320
821
  })];
321
822
  }
@@ -337,6 +838,11 @@ describe("Full example", () => {
337
838
  >> x = "Hello"
338
839
  >> print(x)
339
840
 
841
+ Attributes:
842
+ attr1 (str): Description of attr1.
843
+
844
+ attr2 (int): Description of attr2.
845
+
340
846
  Args:
341
847
  somebody (str, optional): Somebody's name. This can be any string
342
848
  representing a person, whether it's a first name, full name,
@@ -350,10 +856,26 @@ describe("Full example", () => {
350
856
  codename (e.g., 'Agent X'). It's used primarily for display
351
857
  purposes, logging, or greeting messages and is not required to be
352
858
  unique or validated unless specified by the caller.
859
+
860
+ Examples:
861
+ >> print("class-doc")
862
+
863
+ See Also:
864
+ RelatedClass
865
+ helper_function
866
+
867
+ Warning:
868
+ This class is experimental.
869
+
870
+ Deprecated:
871
+ Use NewClass instead.
872
+
873
+ Note:
874
+ Do not include the 'self' parameter in the Args section.
353
875
  """
354
876
  just_name = None
355
- name_and_type: number = None
356
- name_type_and_value: number = 12
877
+ name_and_type: int = None
878
+ name_type_and_value: int = 12
357
879
 
358
880
 
359
881
  `);
@@ -372,16 +894,17 @@ describe("Full example", () => {
372
894
  parameters: [{
373
895
  name: "somebody",
374
896
  type: "str",
375
- optional: true,
376
897
  default: "John Doe",
377
- 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\"."
898
+ 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."
378
899
  }, {
379
900
  name: "somebody2",
380
901
  type: "str",
381
902
  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."
382
903
  }],
383
904
  returns: "The return value. True for success, False otherwise.",
905
+ yields: "int: The next number in the sequence.",
384
906
  raises: ["ValueError: If somebody2 is equal to somebody."],
907
+ note: "This function can be used as both a regular function and a generator.",
385
908
  style: "google"
386
909
  });
387
910
  const res = toSourceText([_$createComponent(py.FunctionDeclaration, {
@@ -436,8 +959,14 @@ describe("Full example", () => {
436
959
  Returns:
437
960
  The return value. True for success, False otherwise.
438
961
 
962
+ Yields:
963
+ int: The next number in the sequence.
964
+
439
965
  Raises:
440
966
  ValueError: If somebody2 is equal to somebody.
967
+
968
+ Note:
969
+ This function can be used as both a regular function and a generator.
441
970
  """
442
971
  just_name = None
443
972
  name_and_type: number = None
@@ -464,7 +993,14 @@ describe("Full example", () => {
464
993
  `);
465
994
  });
466
995
  it("classic enum with explicit values", () => {
467
- const result = toSourceText([_$createComponent(py.EnumDeclaration, {
996
+ const doc = _$createComponent(py.ClassDoc, {
997
+ get description() {
998
+ return [_$createComponent(Prose, {
999
+ children: "An enum representing colors."
1000
+ })];
1001
+ }
1002
+ });
1003
+ const result = toSourceText([_$createComponent(py.ClassEnumDeclaration, {
468
1004
  name: "Color",
469
1005
  baseType: "IntEnum",
470
1006
  members: [{
@@ -480,22 +1016,286 @@ describe("Full example", () => {
480
1016
  value: "3",
481
1017
  doc: "The color blue."
482
1018
  }],
483
- doc: "An enum representing colors."
1019
+ doc: doc
484
1020
  })], {
485
1021
  externals: [enumModule]
486
1022
  });
487
1023
  const expected = d`
488
1024
  from enum import IntEnum
489
1025
 
490
- # An enum representing colors.
491
1026
  class Color(IntEnum):
492
- RED = 1 # The color red.
493
- GREEN = 2 # The color green.
494
- BLUE = 3 # The color blue.
1027
+ """
1028
+ An enum representing colors.
1029
+ """
1030
+
1031
+ RED = 1 #: The color red.
1032
+ GREEN = 2 #: The color green.
1033
+ BLUE = 3 #: The color blue.
495
1034
 
496
1035
 
497
1036
  `;
498
1037
  expect(result).toRenderTo(expected);
499
1038
  });
1039
+ it("ModuleDoc with SourceFile integration", () => {
1040
+ const moduleDoc = _$createComponent(py.ModuleDoc, {
1041
+ get description() {
1042
+ return [_$createComponent(Prose, {
1043
+ children: "This module provides utility functions for data processing. It includes functions for validation, transformation, and analysis."
1044
+ })];
1045
+ },
1046
+ attributes: [{
1047
+ name: "DEFAULT_TIMEOUT",
1048
+ type: "int",
1049
+ children: "Default timeout value in seconds."
1050
+ }, {
1051
+ name: "MAX_RETRIES",
1052
+ type: "int",
1053
+ children: "Maximum number of retry attempts."
1054
+ }],
1055
+ todo: ["Add caching functionality", "Improve error messages"],
1056
+ style: "google"
1057
+ });
1058
+ const content = _$createComponent(py.SourceFile, {
1059
+ path: "utils.py",
1060
+ doc: moduleDoc,
1061
+ get children() {
1062
+ return [_$createComponent(py.VariableDeclaration, {
1063
+ name: "DEFAULT_TIMEOUT",
1064
+ initializer: 30
1065
+ }), _$createComponent(py.VariableDeclaration, {
1066
+ name: "MAX_RETRIES",
1067
+ initializer: 3
1068
+ }), _$createComponent(py.FunctionDeclaration, {
1069
+ name: "process_data",
1070
+ children: "pass"
1071
+ })];
1072
+ }
1073
+ });
1074
+ const res = toSourceTextMultiple([content]);
1075
+ const file = res.contents.find(f => f.kind === "file" && f.path === "utils.py");
1076
+ expect(file).toBeDefined();
1077
+ assertFileContents(res, {
1078
+ "utils.py": d`
1079
+ """
1080
+ This module provides utility functions for data processing. It includes
1081
+ functions for validation, transformation, and analysis.
1082
+
1083
+ Attributes:
1084
+ DEFAULT_TIMEOUT (int): Default timeout value in seconds.
1085
+
1086
+ MAX_RETRIES (int): Maximum number of retry attempts.
1087
+
1088
+ Todo:
1089
+ * Add caching functionality
1090
+ * Improve error messages
1091
+ """
1092
+
1093
+
1094
+ default_timeout = 30
1095
+
1096
+ max_retries = 3
1097
+
1098
+ def process_data():
1099
+ pass
1100
+
1101
+
1102
+ `
1103
+ });
1104
+ });
1105
+ it("GeneratorDoc with FunctionDeclaration integration", () => {
1106
+ const generatorDoc = _$createComponent(py.GeneratorDoc, {
1107
+ get description() {
1108
+ return [_$createComponent(Prose, {
1109
+ children: "A generator function that yields fibonacci numbers. This is an efficient way to generate the sequence on demand."
1110
+ })];
1111
+ },
1112
+ parameters: [{
1113
+ name: "n",
1114
+ type: "int",
1115
+ doc: "Number of fibonacci numbers to generate."
1116
+ }],
1117
+ yields: "int: The next fibonacci number in the sequence.",
1118
+ style: "google"
1119
+ });
1120
+ const result = toSourceText([_$createComponent(py.FunctionDeclaration, {
1121
+ name: "fibonacci_generator",
1122
+ doc: generatorDoc,
1123
+ children: "yield 0"
1124
+ })]);
1125
+ expect(result).toRenderTo(d`
1126
+ def fibonacci_generator():
1127
+ """
1128
+ A generator function that yields fibonacci numbers. This is an efficient way
1129
+ to generate the sequence on demand.
1130
+
1131
+ Args:
1132
+ n (int): Number of fibonacci numbers to generate.
1133
+
1134
+ Yields:
1135
+ int: The next fibonacci number in the sequence.
1136
+ """
1137
+ yield 0
1138
+
1139
+
1140
+ `);
1141
+ });
1142
+ it("ExceptionDoc with ClassDeclaration integration", () => {
1143
+ const exceptionDoc = _$createComponent(py.ExceptionDoc, {
1144
+ get description() {
1145
+ return [_$createComponent(Prose, {
1146
+ children: "Custom exception raised when data validation fails. This exception includes details about the validation error."
1147
+ })];
1148
+ },
1149
+ attributes: [{
1150
+ name: "field_name",
1151
+ type: "str",
1152
+ children: "Name of the field that failed validation."
1153
+ }, {
1154
+ name: "error_code",
1155
+ type: "int",
1156
+ children: "Numeric error code for the validation failure."
1157
+ }],
1158
+ style: "google"
1159
+ });
1160
+ const result = toSourceText([_$createComponent(py.ClassDeclaration, {
1161
+ name: "ValidationError",
1162
+ bases: ["Exception"],
1163
+ doc: exceptionDoc,
1164
+ get children() {
1165
+ return _$createComponent(py.StatementList, {
1166
+ get children() {
1167
+ return [_$createComponent(py.VariableDeclaration, {
1168
+ name: "field_name",
1169
+ type: "str"
1170
+ }), _$createComponent(py.VariableDeclaration, {
1171
+ name: "error_code",
1172
+ type: "int"
1173
+ })];
1174
+ }
1175
+ });
1176
+ }
1177
+ })]);
1178
+ expect(result).toRenderTo(d`
1179
+ class ValidationError(Exception):
1180
+ """
1181
+ Custom exception raised when data validation fails. This exception includes
1182
+ details about the validation error.
1183
+
1184
+ Attributes:
1185
+ field_name (str): Name of the field that failed validation.
1186
+
1187
+ error_code (int): Numeric error code for the validation failure.
1188
+ """
1189
+ field_name: str = None
1190
+ error_code: int = None
1191
+
1192
+
1193
+ `);
1194
+ });
1195
+ it("PropertyDoc with FunctionDeclaration (as property method) integration", () => {
1196
+ const propertyDoc = _$createComponent(py.PropertyDoc, {
1197
+ get description() {
1198
+ return [_$createComponent(Prose, {
1199
+ children: "The full name of the person, combining first and last name. This property automatically formats the name with proper capitalization."
1200
+ })];
1201
+ },
1202
+ style: "google"
1203
+ });
1204
+ const result = toSourceText([_$createComponent(py.ClassDeclaration, {
1205
+ name: "Person",
1206
+ get children() {
1207
+ return _$createComponent(py.PropertyDeclaration, {
1208
+ name: "full_name",
1209
+ doc: propertyDoc,
1210
+ type: "str",
1211
+ children: "return \"John Doe\""
1212
+ });
1213
+ }
1214
+ })]);
1215
+ expect(result).toRenderTo(d`
1216
+ class Person:
1217
+ @property
1218
+ def full_name(self) -> str:
1219
+ """
1220
+ The full name of the person, combining first and last name. This
1221
+ property automatically formats the name with proper capitalization.
1222
+ """
1223
+ return "John Doe"
1224
+
1225
+
1226
+
1227
+
1228
+
1229
+ `);
1230
+ });
1231
+ it("MethodDoc with FunctionDeclaration (inside class) integration", () => {
1232
+ const methodDoc = _$createComponent(py.MethodDoc, {
1233
+ get description() {
1234
+ return [_$createComponent(Prose, {
1235
+ children: "Validates the input data according to the defined schema. This method performs comprehensive validation including type checking."
1236
+ })];
1237
+ },
1238
+ parameters: [{
1239
+ name: "data",
1240
+ type: "dict",
1241
+ doc: "The data dictionary to validate."
1242
+ }, {
1243
+ name: "strict",
1244
+ type: "bool",
1245
+ default: "True",
1246
+ doc: "Whether to enforce strict validation rules."
1247
+ }],
1248
+ returns: "bool: True if validation passes, False otherwise.",
1249
+ raises: ["ValidationError: If data format is invalid."],
1250
+ note: "This method modifies the internal validation state.",
1251
+ style: "google"
1252
+ });
1253
+ const result = toSourceText([_$createComponent(py.ClassDeclaration, {
1254
+ name: "DataValidator",
1255
+ get children() {
1256
+ return _$createComponent(py.MethodDeclaration, {
1257
+ name: "validate",
1258
+ doc: methodDoc,
1259
+ parameters: [{
1260
+ name: "data",
1261
+ type: "dict"
1262
+ }, {
1263
+ name: "strict",
1264
+ type: "bool",
1265
+ default: true
1266
+ }],
1267
+ returnType: "bool",
1268
+ children: "return self.validate(data, strict)"
1269
+ });
1270
+ }
1271
+ })]);
1272
+ expect(result).toRenderTo(d`
1273
+ class DataValidator:
1274
+ def validate(self, data: dict, strict: bool = True) -> bool:
1275
+ """
1276
+ Validates the input data according to the defined schema. This method
1277
+ performs comprehensive validation including type checking.
1278
+
1279
+ Args:
1280
+ data (dict): The data dictionary to validate.
1281
+
1282
+ strict (bool, optional): Whether to enforce strict validation rules.
1283
+ Defaults to "True".
1284
+
1285
+ Returns:
1286
+ bool: True if validation passes, False otherwise.
1287
+
1288
+ Raises:
1289
+ ValidationError: If data format is invalid.
1290
+
1291
+ Note:
1292
+ This method modifies the internal validation state.
1293
+ """
1294
+ return self.validate(data, strict)
1295
+
1296
+
1297
+
1298
+ `);
1299
+ });
500
1300
  });
501
1301
  //# sourceMappingURL=pydocs.test.js.map