@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,31 @@
1
+ import { NamePolicyContext } from "@alloy-js/core";
2
+ import { Children } from "@alloy-js/core/jsx-runtime";
3
+
4
+ export interface NoNamePolicyProps {
5
+ children: Children;
6
+ }
7
+
8
+ /**
9
+ * A wrapper component that disables name policy transformation for its children.
10
+ *
11
+ * This is useful for components that need to preserve exact names without applying
12
+ * naming conventions, such as Python dunder methods like `__init__`, `__str__`, etc.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <NoNamePolicy>
17
+ * <FunctionDeclaration name="__init__" instanceFunction>
18
+ * // Function content
19
+ * </FunctionDeclaration>
20
+ * </NoNamePolicy>
21
+ * ```
22
+ *
23
+ * This ensures `__init__` stays as `__init__` without name policy transformation.
24
+ */
25
+ export function NoNamePolicy(props: NoNamePolicyProps) {
26
+ return (
27
+ <NamePolicyContext.Provider value={undefined}>
28
+ {props.children}
29
+ </NamePolicyContext.Provider>
30
+ );
31
+ }
@@ -0,0 +1,331 @@
1
+ import { For, Indent, List, Prose, Show, childrenArray } from "@alloy-js/core";
2
+ import { Children } from "@alloy-js/core/jsx-runtime";
3
+ import { ParameterDescriptor } from "../parameter-descriptor.js";
4
+ import { Atom } from "./index.js";
5
+
6
+ interface GoogleStyleDocParamTypeProps {
7
+ type?: Children;
8
+ optional?: boolean;
9
+ }
10
+
11
+ function GoogleStyleDocParamType(props: GoogleStyleDocParamTypeProps) {
12
+ return (
13
+ <>
14
+ <Show when={Boolean(props.type)}>
15
+ {" ("}
16
+ {props.type}
17
+ <Show when={props.optional}>{", optional"}</Show>
18
+ {")"}
19
+ </Show>
20
+ </>
21
+ );
22
+ }
23
+
24
+ interface GoogleStyleDocParamNameProps {
25
+ name: Children;
26
+ }
27
+
28
+ function GoogleStyleDocParamName(props: GoogleStyleDocParamNameProps) {
29
+ return <>{props.name}</>;
30
+ }
31
+
32
+ interface GoogleStyleDocParamDescriptionProps {
33
+ children?: Children;
34
+ defaultValue?: Children;
35
+ }
36
+
37
+ function GoogleStyleDocParamDescription(
38
+ props: GoogleStyleDocParamDescriptionProps,
39
+ ) {
40
+ return (
41
+ <Show when={Boolean(props.children)}>
42
+ {": "}
43
+ <align width={4}>
44
+ <Prose>{props.children}</Prose>
45
+ <Show when={Boolean(props.defaultValue)}>
46
+ {" "}
47
+ Defaults to <Atom jsValue={props.defaultValue}></Atom>.
48
+ </Show>
49
+ </align>
50
+ </Show>
51
+ );
52
+ }
53
+
54
+ export interface GoogleStyleDocParamProps {
55
+ name: Children;
56
+ type?: Children;
57
+ children?: Children;
58
+ optional?: boolean;
59
+ defaultValue?: Children;
60
+ }
61
+
62
+ /**
63
+ * Create a GoogleStyleDoc parameter.
64
+ */
65
+ export function GoogleStyleDocParam(props: GoogleStyleDocParamProps) {
66
+ return (
67
+ <>
68
+ <GoogleStyleDocParamName name={props.name} />
69
+ <GoogleStyleDocParamType type={props.type} optional={props.optional} />
70
+ <GoogleStyleDocParamDescription
71
+ children={props.children}
72
+ defaultValue={props.defaultValue}
73
+ />
74
+ </>
75
+ );
76
+ }
77
+
78
+ export interface GoogleStyleDocParamsProps {
79
+ parameters: ParameterDescriptor[] | string[];
80
+ }
81
+
82
+ /**
83
+ * A component that creates a GoogleStyleDoc block for parameters.
84
+ */
85
+ export function GoogleStyleDocParams(props: GoogleStyleDocParamsProps) {
86
+ const parameters = normalizeParametersForDoc(props.parameters);
87
+ return (
88
+ <>
89
+ {"Args:"}
90
+ <Indent>
91
+ <List doubleHardline>
92
+ {parameters.map((param) => (
93
+ <GoogleStyleDocParam
94
+ name={param.name}
95
+ type={param.type}
96
+ optional={param.optional}
97
+ >
98
+ {param.doc}
99
+ </GoogleStyleDocParam>
100
+ ))}
101
+ </List>
102
+ </Indent>
103
+ </>
104
+ );
105
+ }
106
+
107
+ export interface GoogleStyleDocReturnProps {
108
+ message: string;
109
+ }
110
+
111
+ /**
112
+ * A component that creates a GoogleStyleDoc block for parameters.
113
+ */
114
+ export function GoogleStyleDocReturn(props: GoogleStyleDocReturnProps) {
115
+ return (
116
+ <>
117
+ {"Returns:"}
118
+ <Indent>{props.message}</Indent>
119
+ </>
120
+ );
121
+ }
122
+
123
+ export interface GoogleStyleDocRaisesProps {
124
+ message: string;
125
+ }
126
+
127
+ /**
128
+ * A component that creates a GoogleStyleDoc block for parameters.
129
+ */
130
+ export function GoogleStyleDocRaises(props: GoogleStyleDocRaisesProps) {
131
+ return (
132
+ <>
133
+ {"Raises:"}
134
+ <Indent>{props.message}</Indent>
135
+ </>
136
+ );
137
+ }
138
+
139
+ export interface GoogleStyleFunctionDocProps
140
+ extends Omit<FunctionDocProps, "style"> {}
141
+
142
+ /**
143
+ * A component that creates a GoogleStyleFunctionDoc block for parameters.
144
+ */
145
+ export function GoogleStyleFunctionDoc(props: GoogleStyleFunctionDocProps) {
146
+ // We are creating a list instead of relying on <Show> because otherwise
147
+ // <List> would render spaces between the elements even if <Show> evaluates to false.
148
+ const children = [];
149
+ if (props.description !== undefined) {
150
+ children.push(
151
+ <List doubleHardline>{props.description.map((param) => param)}</List>,
152
+ );
153
+ }
154
+ if (props.parameters !== undefined && props.parameters.length > 0) {
155
+ children.push(<GoogleStyleDocParams parameters={props.parameters} />);
156
+ }
157
+ if (props.returns !== undefined) {
158
+ children.push(<GoogleStyleDocReturn message={props.returns} />);
159
+ }
160
+ if (props.raises !== undefined && props.raises.length > 0) {
161
+ children.push(
162
+ props.raises!.map((param) => <GoogleStyleDocRaises message={param} />),
163
+ );
164
+ }
165
+ return <PyDoc>{children}</PyDoc>;
166
+ }
167
+
168
+ export interface FunctionDocProps {
169
+ description: Children[];
170
+ parameters?: ParameterDescriptor[] | string[];
171
+ returns?: string;
172
+ raises?: string[];
173
+ style?: "google";
174
+ }
175
+
176
+ /**
177
+ * A component that creates a FunctionDoc block for parameters.
178
+ */
179
+ export function FunctionDoc(props: FunctionDocProps) {
180
+ const style = props.style ?? "google";
181
+ if (style === "google") {
182
+ return (
183
+ <GoogleStyleFunctionDoc
184
+ description={props.description}
185
+ parameters={props.parameters}
186
+ returns={props.returns}
187
+ raises={props.raises}
188
+ />
189
+ );
190
+ }
191
+ }
192
+
193
+ export interface ClassDocProps {
194
+ description: Children[];
195
+ parameters?: ParameterDescriptor[] | string[];
196
+ style?: "google";
197
+ }
198
+
199
+ /**
200
+ * A component that creates a ClassDoc block for parameters.
201
+ */
202
+ export function ClassDoc(props: ClassDocProps) {
203
+ const style = props.style ?? "google";
204
+ if (style === "google") {
205
+ return (
206
+ <GoogleStyleClassDoc
207
+ description={props.description}
208
+ parameters={props.parameters}
209
+ />
210
+ );
211
+ }
212
+ }
213
+
214
+ export interface GoogleStyleClassDocProps
215
+ extends Omit<ClassDocProps, "style"> {}
216
+
217
+ /**
218
+ * A component that creates a GoogleStyleClassDoc block for parameters.
219
+ */
220
+ export function GoogleStyleClassDoc(props: GoogleStyleClassDocProps) {
221
+ // We are creating a list instead of relying on <Show> because otherwise
222
+ // <List> would render spaces between the elements even if <Show> evaluates to false.
223
+ const children = [];
224
+ if (props.description !== undefined) {
225
+ children.push(
226
+ <List doubleHardline>{props.description.map((param) => param)}</List>,
227
+ );
228
+ }
229
+ if (props.parameters !== undefined && props.parameters.length > 0) {
230
+ children.push(<GoogleStyleDocParams parameters={props.parameters} />);
231
+ }
232
+ return <PyDoc>{children}</PyDoc>;
233
+ }
234
+
235
+ export interface PyDocExampleProps {
236
+ children: Children;
237
+ }
238
+
239
+ /**
240
+ * Create a PyDoc example, which is prepended by \>\>.
241
+ */
242
+ export function PyDocExample(props: PyDocExampleProps) {
243
+ const children = childrenArray(() => props.children);
244
+ let lines: string[] = [];
245
+
246
+ if (children.length === 1 && typeof children[0] === "string") {
247
+ // Split, trim each line, and filter out empty lines
248
+ lines = children[0]
249
+ .split(/\r?\n/)
250
+ .map((line) => line.trim())
251
+ .filter((line) => line.length > 0);
252
+ } else {
253
+ // For non-string children, filter out empty/whitespace-only strings
254
+ lines = children
255
+ .map((child) => (typeof child === "string" ? child : ""))
256
+ .map((line) => line.trim())
257
+ .filter((line) => line.length > 0);
258
+ }
259
+
260
+ return (
261
+ <>
262
+ <For each={lines}>
263
+ {(line) => (
264
+ <>
265
+ {">> "}
266
+ {line}
267
+ </>
268
+ )}
269
+ </For>
270
+ </>
271
+ );
272
+ }
273
+
274
+ function normalizeParametersForDoc(
275
+ parameters: ParameterDescriptor[] | string[],
276
+ ): ParameterDescriptor[] {
277
+ if (parameters.some((p) => typeof p === "string")) {
278
+ return [];
279
+ }
280
+
281
+ return parameters as ParameterDescriptor[];
282
+ }
283
+
284
+ export interface PyDocProps {
285
+ children: Children;
286
+ }
287
+
288
+ /**
289
+ * A PyDoc comment. The children of this component are joined with two hard
290
+ * linebreaks. This is useful for creating PyDoc comments with multiple paragraphs.
291
+ */
292
+ export function PyDoc(props: PyDocProps) {
293
+ const children = childrenArray(() => props.children);
294
+ return (
295
+ <>
296
+ {'"""'}
297
+ <hbr />
298
+ <List doubleHardline>{children}</List>
299
+ <hbr />
300
+ {'"""'}
301
+ <hbr />
302
+ </>
303
+ );
304
+ }
305
+
306
+ export interface SimpleCommentBlockProps {
307
+ children: Children;
308
+ }
309
+
310
+ export function SimpleCommentBlock(props: SimpleCommentBlockProps) {
311
+ return (
312
+ <>
313
+ #{" "}
314
+ <align string="# ">
315
+ <Prose>{props.children}</Prose>
316
+ </align>
317
+ </>
318
+ );
319
+ }
320
+
321
+ export interface SimpleInlineCommentProps {
322
+ children: Children;
323
+ }
324
+
325
+ export function SimpleInlineComment(props: SimpleInlineCommentProps) {
326
+ return (
327
+ <>
328
+ {" "}# <Prose>{props.children}</Prose>
329
+ </>
330
+ );
331
+ }
@@ -0,0 +1,26 @@
1
+ import { Block, Children } from "@alloy-js/core";
2
+
3
+ /**
4
+ * A Python block component that can be used to render a block of Python code.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * <PythonBlock opener="def my_function()">
9
+ * <VariableDeclaration name="x" type="int" />
10
+ * <VariableDeclaration name="y" type="str" />
11
+ * </PythonBlock>
12
+ * ```
13
+ * renders to
14
+ * ```py
15
+ * def my_function():
16
+ * x: int = None
17
+ * y: str = None
18
+ * ```
19
+ */
20
+ export function PythonBlock(props: { children: Children; opener?: string }) {
21
+ return (
22
+ <Block opener={props.opener ?? ""} closer="">
23
+ {props.children}
24
+ </Block>
25
+ );
26
+ }
@@ -0,0 +1,21 @@
1
+ import { computed, emitSymbol, Refkey } from "@alloy-js/core";
2
+ import { ref } from "../symbols/index.js";
3
+
4
+ export interface ReferenceProps {
5
+ refkey: Refkey;
6
+ }
7
+
8
+ /**
9
+ * A Python reference to a symbol, such as a variable, function, or class.
10
+ *
11
+ * @remarks
12
+ * This component is used to render references to symbols in Python code.
13
+ * It takes a `refkey` prop which is the key of the symbol to reference.
14
+ */
15
+ export function Reference({ refkey }: ReferenceProps) {
16
+ const reference = ref(refkey);
17
+ const symbolRef = computed(() => reference()[1]);
18
+
19
+ emitSymbol(symbolRef);
20
+ return <>{reference()[0]}</>;
21
+ }
@@ -0,0 +1,93 @@
1
+ import {
2
+ ComponentContext,
3
+ SourceFile as CoreSourceFile,
4
+ createNamedContext,
5
+ List,
6
+ Scope,
7
+ Show,
8
+ SourceDirectoryContext,
9
+ useContext,
10
+ type Children,
11
+ } from "@alloy-js/core";
12
+ import { join } from "pathe";
13
+ import { PythonModuleScope } from "../symbols/index.js";
14
+ import { ImportStatements } from "./ImportStatement.js";
15
+ import { Reference } from "./Reference.js";
16
+
17
+ export interface PythonSourceFileContext {
18
+ scope: PythonModuleScope;
19
+ /** The module name for this file, e.g. 'test' for test.py */
20
+ module: string;
21
+ }
22
+
23
+ export const PythonSourceFileContext: ComponentContext<PythonSourceFileContext> =
24
+ createNamedContext("@alloy-js/python SourceFile");
25
+
26
+ export function useSourceFile() {
27
+ return useContext(PythonSourceFileContext)!;
28
+ }
29
+
30
+ export interface SourceFileProps {
31
+ /**
32
+ * The path to the file relative to the source directory.
33
+ */
34
+ path: string;
35
+ /**
36
+ * Content to add to the file, such as function definitions, class definitions, and variable declarations.
37
+ */
38
+ children?: Children;
39
+ /**
40
+ * Header comment to add to the file, which will be rendered at the top of the file.
41
+ */
42
+ header?: Children;
43
+ /**
44
+ * Comment to add to the header, which will be rendered as a comment in the file.
45
+ */
46
+ headerComment?: string;
47
+ }
48
+
49
+ /**
50
+ * A Python source file component that represents a Python file in the source directory.
51
+ * It provides a scope for the file, which is a `PythonModuleScope` that contains
52
+ * all the symbols defined in the file, such as functions, classes, and variables.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * <SourceFile path="test.py">
57
+ * <FunctionDeclaration name="test" />
58
+ * </SourceFile>
59
+ * ```
60
+ * renders to
61
+ * ```py
62
+ * def test():
63
+ * pass
64
+ * ```
65
+ */
66
+ export function SourceFile(props: SourceFileProps) {
67
+ const directoryContext = useContext(SourceDirectoryContext)!;
68
+ const currentDir = directoryContext.path;
69
+ // Name of the scope is derived from the file path, minus the .py extension, and with slashes replaced by dots
70
+ const path: string = join(currentDir, props.path)
71
+ .replace(/\.py$/, "")
72
+ .replace(/\//g, ".");
73
+ const scope = new PythonModuleScope(path);
74
+ const sfContext: PythonSourceFileContext = {
75
+ scope: scope,
76
+ module: path,
77
+ };
78
+
79
+ return (
80
+ <CoreSourceFile path={props.path} filetype="py" reference={Reference}>
81
+ <Show when={scope.importedModules.size > 0}>
82
+ <ImportStatements records={scope.importedModules} />
83
+ <hbr />
84
+ <hbr />
85
+ </Show>
86
+ <PythonSourceFileContext.Provider value={sfContext}>
87
+ <Scope value={scope} kind="source-file">
88
+ <List doubleHardline>{props.children}</List>
89
+ </Scope>
90
+ </PythonSourceFileContext.Provider>
91
+ </CoreSourceFile>
92
+ );
93
+ }
@@ -0,0 +1,28 @@
1
+ import { Children, List } from "@alloy-js/core";
2
+
3
+ export interface StatementListProps {
4
+ children: Children;
5
+ }
6
+
7
+ /**
8
+ * A Python statement list, which is a list of statements that can be rendered
9
+ * in a Python source file.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <StatementList>
14
+ * <FunctionDeclaration name="test" />
15
+ * <VariableDeclaration name="x" value={42} />
16
+ * </StatementList>
17
+ * ```
18
+ * renders to
19
+ * ```py
20
+ * def test():
21
+ * pass
22
+ *
23
+ * x = 42
24
+ * ```
25
+ */
26
+ export function StatementList(props: StatementListProps) {
27
+ return <List hardline>{props.children}</List>;
28
+ }
@@ -0,0 +1,180 @@
1
+ import {
2
+ Children,
3
+ Declaration as CoreDeclaration,
4
+ Name,
5
+ OutputScope,
6
+ OutputSymbolFlags,
7
+ Show,
8
+ createSymbolSlot,
9
+ effect,
10
+ emitSymbol,
11
+ memo,
12
+ useMemberScope,
13
+ useScope,
14
+ } from "@alloy-js/core";
15
+ import { createPythonSymbol } from "../symbol-creation.js";
16
+ import { Atom } from "./Atom.jsx";
17
+ import { BaseDeclarationProps } from "./Declaration.jsx";
18
+ import { SimpleCommentBlock } from "./index.js";
19
+
20
+ export interface VariableDeclarationProps extends BaseDeclarationProps {
21
+ /**
22
+ * The initial value of the variable.
23
+ */
24
+ initializer?: Children;
25
+ /**
26
+ * The type of the variable. Used only for type annotation. Optional.
27
+ */
28
+ type?: Children;
29
+ /**
30
+ * Indicates if we should omit the None assignment. Optional.
31
+ */
32
+ omitNone?: boolean;
33
+ /**
34
+ * Indicates if this is a call statement variable. Optional.
35
+ * This is used to handle cases where the variable is part of a call statement.
36
+ */
37
+ callStatementVar?: boolean;
38
+ /**
39
+ * Indicates if this variable is an instance variable. Optional.
40
+ * This is used to handle cases where the variable is part of a class instance.
41
+ */
42
+ instanceVariable?: boolean;
43
+ }
44
+
45
+ /**
46
+ * A variable declaration component for Python.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * <VariableDeclaration
51
+ * name="myVar"
52
+ * type="int"
53
+ * initializer={42} // Initial value
54
+ * />
55
+ * <VariableDeclaration
56
+ * name="myOtherVar"
57
+ * type="str"
58
+ * omitNone={true}
59
+ * />
60
+ * <VariableDeclaration
61
+ * name="myCallStmtVar"
62
+ * callStatementVar={true}
63
+ * initializer={12}
64
+ * />
65
+ * VariableDeclaration
66
+ * name=""
67
+ * callStatementVar={true}
68
+ * initializer={12}
69
+ * />
70
+ * ```
71
+ * renders to
72
+ * ```py
73
+ * myVar: int = 42
74
+ * myOtherVar: str
75
+ * myCallStmtVar=12
76
+ * 12
77
+ * ```
78
+ */
79
+ export function VariableDeclaration(props: VariableDeclarationProps) {
80
+ const instanceVariable = props.instanceVariable ?? false;
81
+ const TypeSymbolSlot = createSymbolSlot();
82
+ const ValueTypeSymbolSlot = createSymbolSlot();
83
+ const memberScope = useMemberScope();
84
+ let scope: OutputScope | undefined = undefined;
85
+ // Only consider the member scope if this is an instance variable
86
+ if (memberScope !== undefined && instanceVariable) {
87
+ scope = memberScope.instanceMembers!;
88
+ } else {
89
+ scope = useScope();
90
+ }
91
+
92
+ const sym = createPythonSymbol(
93
+ props.name,
94
+ {
95
+ scope: scope,
96
+ refkeys: props.refkey,
97
+ },
98
+ "variable",
99
+ true,
100
+ );
101
+ emitSymbol(sym);
102
+ // Handle optional type annotation
103
+ const type = memo(() => {
104
+ if (!props.type || props.callStatementVar) return undefined;
105
+ return (
106
+ <>
107
+ : <TypeSymbolSlot>{props.type}</TypeSymbolSlot>
108
+ </>
109
+ );
110
+ });
111
+
112
+ effect(() => {
113
+ if (TypeSymbolSlot.ref.value) {
114
+ const takenSymbols = TypeSymbolSlot.ref.value;
115
+ for (const symbol of takenSymbols) {
116
+ // If the symbol is a type, instantiate it
117
+ symbol.instantiateTo(sym);
118
+ }
119
+ } else if (ValueTypeSymbolSlot.ref.value) {
120
+ const takenSymbols = ValueTypeSymbolSlot.ref.value;
121
+ for (const symbol of takenSymbols) {
122
+ // ignore non-transient symbols (likely not the result of an
123
+ // expression).
124
+ if (symbol.flags & OutputSymbolFlags.Transient) {
125
+ symbol.moveTo(sym);
126
+ }
127
+ }
128
+ }
129
+ });
130
+
131
+ // If we receive a symbol, resolve it to a name
132
+ const value =
133
+ typeof props.initializer === "object" ?
134
+ memo(() => props.initializer)
135
+ : props.initializer;
136
+ const assignmentOperator = props.callStatementVar ? "=" : " = ";
137
+ const getRightSide = () => {
138
+ // Early return for omitNone case
139
+ if (props.omitNone && props.initializer === undefined) {
140
+ return [false, ""];
141
+ }
142
+
143
+ // Handle null/undefined values
144
+ if (value === null || value === undefined) {
145
+ return [true, <>None</>];
146
+ }
147
+
148
+ let renderRightSideOperator = true;
149
+ // Call statement with no name
150
+ if (
151
+ props.callStatementVar &&
152
+ (props.name === undefined || props.name === "")
153
+ ) {
154
+ renderRightSideOperator = false;
155
+ }
156
+
157
+ // Standard assignment
158
+ return [
159
+ renderRightSideOperator,
160
+ <ValueTypeSymbolSlot>
161
+ <Atom jsValue={value} />
162
+ </ValueTypeSymbolSlot>,
163
+ ];
164
+ };
165
+ const [renderRightSideOperator, rightSide] = getRightSide();
166
+ return (
167
+ <>
168
+ <Show when={Boolean(props.doc)}>
169
+ <SimpleCommentBlock children={props.doc} />
170
+ <hbr />
171
+ </Show>
172
+ <CoreDeclaration symbol={sym}>
173
+ {<Name />}
174
+ {type}
175
+ {renderRightSideOperator && assignmentOperator}
176
+ {rightSide}
177
+ </CoreDeclaration>
178
+ </>
179
+ );
180
+ }