@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.
- package/CHANGELOG.md +3 -0
- package/LICENSE +7 -0
- package/api-extractor.json +4 -0
- package/dist/src/builtins/python.d.ts +9 -0
- package/dist/src/builtins/python.d.ts.map +1 -0
- package/dist/src/builtins/python.js +17 -0
- package/dist/src/components/Atom.d.ts +19 -0
- package/dist/src/components/Atom.d.ts.map +1 -0
- package/dist/src/components/Atom.js +82 -0
- package/dist/src/components/CallSignature.d.ts +79 -0
- package/dist/src/components/CallSignature.d.ts.map +1 -0
- package/dist/src/components/CallSignature.js +201 -0
- package/dist/src/components/ClassDeclaration.d.ts +37 -0
- package/dist/src/components/ClassDeclaration.d.ts.map +1 -0
- package/dist/src/components/ClassDeclaration.js +83 -0
- package/dist/src/components/ClassInstantiation.d.ts +24 -0
- package/dist/src/components/ClassInstantiation.d.ts.map +1 -0
- package/dist/src/components/ClassInstantiation.js +35 -0
- package/dist/src/components/Declaration.d.ts +48 -0
- package/dist/src/components/Declaration.d.ts.map +1 -0
- package/dist/src/components/Declaration.js +37 -0
- package/dist/src/components/EnumDeclaration.d.ts +164 -0
- package/dist/src/components/EnumDeclaration.d.ts.map +1 -0
- package/dist/src/components/EnumDeclaration.js +278 -0
- package/dist/src/components/EnumMember.d.ts +46 -0
- package/dist/src/components/EnumMember.d.ts.map +1 -0
- package/dist/src/components/EnumMember.js +67 -0
- package/dist/src/components/FunctionCallExpression.d.ts +19 -0
- package/dist/src/components/FunctionCallExpression.d.ts.map +1 -0
- package/dist/src/components/FunctionCallExpression.js +40 -0
- package/dist/src/components/FunctionDeclaration.d.ts +47 -0
- package/dist/src/components/FunctionDeclaration.d.ts.map +1 -0
- package/dist/src/components/FunctionDeclaration.js +107 -0
- package/dist/src/components/ImportStatement.d.ts +39 -0
- package/dist/src/components/ImportStatement.d.ts.map +1 -0
- package/dist/src/components/ImportStatement.js +104 -0
- package/dist/src/components/MemberExpression.d.ts +97 -0
- package/dist/src/components/MemberExpression.d.ts.map +1 -0
- package/dist/src/components/MemberExpression.js +308 -0
- package/dist/src/components/NoNamePolicy.d.ts +23 -0
- package/dist/src/components/NoNamePolicy.d.ts.map +1 -0
- package/dist/src/components/NoNamePolicy.js +27 -0
- package/dist/src/components/PyDoc.d.ts +90 -0
- package/dist/src/components/PyDoc.d.ts.map +1 -0
- package/dist/src/components/PyDoc.js +280 -0
- package/dist/src/components/PythonBlock.d.ts +23 -0
- package/dist/src/components/PythonBlock.d.ts.map +1 -0
- package/dist/src/components/PythonBlock.js +31 -0
- package/dist/src/components/Reference.d.ts +13 -0
- package/dist/src/components/Reference.d.ts.map +1 -0
- package/dist/src/components/Reference.js +18 -0
- package/dist/src/components/SourceFile.d.ts +46 -0
- package/dist/src/components/SourceFile.d.ts.map +1 -0
- package/dist/src/components/SourceFile.js +75 -0
- package/dist/src/components/StatementList.d.ts +25 -0
- package/dist/src/components/StatementList.d.ts.map +1 -0
- package/dist/src/components/StatementList.js +29 -0
- package/dist/src/components/VariableDeclaration.d.ts +62 -0
- package/dist/src/components/VariableDeclaration.d.ts.map +1 -0
- package/dist/src/components/VariableDeclaration.js +131 -0
- package/dist/src/components/index.d.ts +19 -0
- package/dist/src/components/index.d.ts.map +1 -0
- package/dist/src/components/index.js +18 -0
- package/dist/src/create-module.d.ts +16 -0
- package/dist/src/create-module.d.ts.map +1 -0
- package/dist/src/create-module.js +64 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +7 -0
- package/dist/src/name-policy.d.ts +5 -0
- package/dist/src/name-policy.d.ts.map +1 -0
- package/dist/src/name-policy.js +47 -0
- package/dist/src/parameter-descriptor.d.ts +31 -0
- package/dist/src/parameter-descriptor.d.ts.map +1 -0
- package/dist/src/parameter-descriptor.js +1 -0
- package/dist/src/symbol-creation.d.ts +4 -0
- package/dist/src/symbol-creation.d.ts.map +1 -0
- package/dist/src/symbol-creation.js +24 -0
- package/dist/src/symbols/custom-output-scope.d.ts +10 -0
- package/dist/src/symbols/custom-output-scope.d.ts.map +1 -0
- package/dist/src/symbols/custom-output-scope.js +25 -0
- package/dist/src/symbols/index.d.ts +7 -0
- package/dist/src/symbols/index.d.ts.map +1 -0
- package/dist/src/symbols/index.js +6 -0
- package/dist/src/symbols/python-member-scope.d.ts +7 -0
- package/dist/src/symbols/python-member-scope.d.ts.map +1 -0
- package/dist/src/symbols/python-member-scope.js +9 -0
- package/dist/src/symbols/python-module-scope.d.ts +25 -0
- package/dist/src/symbols/python-module-scope.d.ts.map +1 -0
- package/dist/src/symbols/python-module-scope.js +52 -0
- package/dist/src/symbols/python-output-symbol.d.ts +19 -0
- package/dist/src/symbols/python-output-symbol.d.ts.map +1 -0
- package/dist/src/symbols/python-output-symbol.js +22 -0
- package/dist/src/symbols/reference.d.ts +4 -0
- package/dist/src/symbols/reference.d.ts.map +1 -0
- package/dist/src/symbols/reference.js +60 -0
- package/dist/src/symbols/scopes.d.ts +5 -0
- package/dist/src/symbols/scopes.d.ts.map +1 -0
- package/dist/src/symbols/scopes.js +4 -0
- package/dist/src/utils.d.ts +7 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +12 -0
- package/dist/test/callsignatures.test.d.ts +2 -0
- package/dist/test/callsignatures.test.d.ts.map +1 -0
- package/dist/test/callsignatures.test.js +276 -0
- package/dist/test/classdeclarations.test.d.ts +2 -0
- package/dist/test/classdeclarations.test.d.ts.map +1 -0
- package/dist/test/classdeclarations.test.js +397 -0
- package/dist/test/classinstantiations.test.d.ts +2 -0
- package/dist/test/classinstantiations.test.d.ts.map +1 -0
- package/dist/test/classinstantiations.test.js +168 -0
- package/dist/test/enums.test.d.ts +2 -0
- package/dist/test/enums.test.d.ts.map +1 -0
- package/dist/test/enums.test.js +211 -0
- package/dist/test/externals.test.d.ts +2 -0
- package/dist/test/externals.test.d.ts.map +1 -0
- package/dist/test/externals.test.js +219 -0
- package/dist/test/functioncallexpressions.test.d.ts +2 -0
- package/dist/test/functioncallexpressions.test.d.ts.map +1 -0
- package/dist/test/functioncallexpressions.test.js +156 -0
- package/dist/test/functiondeclaration.test.d.ts +2 -0
- package/dist/test/functiondeclaration.test.d.ts.map +1 -0
- package/dist/test/functiondeclaration.test.js +363 -0
- package/dist/test/imports.test.d.ts +2 -0
- package/dist/test/imports.test.d.ts.map +1 -0
- package/dist/test/imports.test.js +262 -0
- package/dist/test/memberexpressions.test.d.ts +2 -0
- package/dist/test/memberexpressions.test.d.ts.map +1 -0
- package/dist/test/memberexpressions.test.js +879 -0
- package/dist/test/namepolicies.test.d.ts +2 -0
- package/dist/test/namepolicies.test.d.ts.map +1 -0
- package/dist/test/namepolicies.test.js +109 -0
- package/dist/test/pydocs.test.d.ts +2 -0
- package/dist/test/pydocs.test.d.ts.map +1 -0
- package/dist/test/pydocs.test.js +500 -0
- package/dist/test/references.test.d.ts +2 -0
- package/dist/test/references.test.d.ts.map +1 -0
- package/dist/test/references.test.js +49 -0
- package/dist/test/sourcefiles.test.d.ts +2 -0
- package/dist/test/sourcefiles.test.d.ts.map +1 -0
- package/dist/test/sourcefiles.test.js +198 -0
- package/dist/test/utils.d.ts +23 -0
- package/dist/test/utils.d.ts.map +1 -0
- package/dist/test/utils.js +88 -0
- package/dist/test/values.test.d.ts +2 -0
- package/dist/test/values.test.d.ts.map +1 -0
- package/dist/test/values.test.js +78 -0
- package/dist/test/variables.test.d.ts +2 -0
- package/dist/test/variables.test.d.ts.map +1 -0
- package/dist/test/variables.test.js +173 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +39 -0
- package/src/builtins/python.ts +20 -0
- package/src/components/Atom.tsx +76 -0
- package/src/components/CallSignature.tsx +251 -0
- package/src/components/ClassDeclaration.tsx +98 -0
- package/src/components/ClassInstantiation.tsx +54 -0
- package/src/components/Declaration.tsx +91 -0
- package/src/components/EnumDeclaration.tsx +291 -0
- package/src/components/EnumMember.tsx +92 -0
- package/src/components/FunctionCallExpression.tsx +36 -0
- package/src/components/FunctionDeclaration.tsx +121 -0
- package/src/components/ImportStatement.tsx +134 -0
- package/src/components/MemberExpression.tsx +456 -0
- package/src/components/NoNamePolicy.tsx +31 -0
- package/src/components/PyDoc.tsx +331 -0
- package/src/components/PythonBlock.tsx +26 -0
- package/src/components/Reference.tsx +21 -0
- package/src/components/SourceFile.tsx +93 -0
- package/src/components/StatementList.tsx +28 -0
- package/src/components/VariableDeclaration.tsx +180 -0
- package/src/components/index.ts +18 -0
- package/src/create-module.ts +102 -0
- package/src/index.ts +7 -0
- package/src/name-policy.ts +101 -0
- package/src/parameter-descriptor.ts +36 -0
- package/src/symbol-creation.ts +36 -0
- package/src/symbols/custom-output-scope.ts +35 -0
- package/src/symbols/index.ts +6 -0
- package/src/symbols/python-member-scope.ts +12 -0
- package/src/symbols/python-module-scope.ts +89 -0
- package/src/symbols/python-output-symbol.ts +36 -0
- package/src/symbols/reference.ts +99 -0
- package/src/symbols/scopes.ts +9 -0
- package/src/utils.ts +27 -0
- package/temp/api.json +7207 -0
- package/test/callsignatures.test.tsx +256 -0
- package/test/classdeclarations.test.tsx +320 -0
- package/test/classinstantiations.test.tsx +159 -0
- package/test/enums.test.tsx +203 -0
- package/test/externals.test.tsx +190 -0
- package/test/functioncallexpressions.test.tsx +145 -0
- package/test/functiondeclaration.test.tsx +327 -0
- package/test/imports.test.tsx +214 -0
- package/test/memberexpressions.test.tsx +725 -0
- package/test/namepolicies.test.tsx +109 -0
- package/test/pydocs.test.tsx +528 -0
- package/test/references.test.tsx +36 -0
- package/test/sourcefiles.test.tsx +131 -0
- package/test/utils.tsx +131 -0
- package/test/values.test.tsx +61 -0
- package/test/variables.test.tsx +153 -0
- package/tsconfig.json +12 -0
- package/tsdoc-metadata.json +11 -0
- package/vitest.config.ts +10 -0
- package/vitest.setup.ts +1 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
List,
|
|
4
|
+
Name,
|
|
5
|
+
OutputSymbolFlags,
|
|
6
|
+
Scope,
|
|
7
|
+
Show,
|
|
8
|
+
childrenArray,
|
|
9
|
+
takeSymbols,
|
|
10
|
+
} from "@alloy-js/core";
|
|
11
|
+
import { createPythonSymbol } from "../symbol-creation.js";
|
|
12
|
+
import {
|
|
13
|
+
BaseDeclarationProps,
|
|
14
|
+
Declaration,
|
|
15
|
+
DeclarationProps,
|
|
16
|
+
} from "./Declaration.js";
|
|
17
|
+
import { PythonBlock } from "./PythonBlock.jsx";
|
|
18
|
+
|
|
19
|
+
export interface ClassDeclarationProps extends BaseDeclarationProps {
|
|
20
|
+
/**
|
|
21
|
+
* The base classes that this class inherits from.
|
|
22
|
+
*/
|
|
23
|
+
bases?: Children[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create a Python class declaration.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* <ClassDeclaration name="MyClass" bases={["BaseClass"]}>
|
|
32
|
+
* <VariableDeclaration name="a" type="int" />
|
|
33
|
+
* <VariableDeclaration name="b" type="str" />
|
|
34
|
+
* <py.FunctionDeclaration name="my_method" parameters={[{ name: "a", type: "int" }, { name: "b", type: "str" }]} returnType="int">
|
|
35
|
+
* return a + b
|
|
36
|
+
* </py.FunctionDeclaration>
|
|
37
|
+
* </ClassDeclaration>
|
|
38
|
+
* ```
|
|
39
|
+
* renders to
|
|
40
|
+
* ```py
|
|
41
|
+
* class MyClass(BaseClass):
|
|
42
|
+
* a: int = None
|
|
43
|
+
* b: str = None
|
|
44
|
+
* def my_method(self, a: int, b: str) -> int:
|
|
45
|
+
* return a + b
|
|
46
|
+
* ```
|
|
47
|
+
* @remarks
|
|
48
|
+
*
|
|
49
|
+
* Any child declarations (methods, fields, nested classes) will be placed
|
|
50
|
+
* in the class scope. This component creates a class scope to hold its
|
|
51
|
+
* members.
|
|
52
|
+
*/
|
|
53
|
+
export function ClassDeclaration(props: ClassDeclarationProps) {
|
|
54
|
+
const basesPart = props.bases && (
|
|
55
|
+
<>
|
|
56
|
+
(<List children={props.bases} comma space />)
|
|
57
|
+
</>
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const sym = createPythonSymbol(
|
|
61
|
+
props.name!,
|
|
62
|
+
{
|
|
63
|
+
refkeys: props.refkey,
|
|
64
|
+
flags:
|
|
65
|
+
(props.flags ?? OutputSymbolFlags.None) |
|
|
66
|
+
OutputSymbolFlags.MemberContainer,
|
|
67
|
+
},
|
|
68
|
+
"class",
|
|
69
|
+
true,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
takeSymbols((memberSymbol) => {
|
|
73
|
+
// Transform emitted symbols into instance/class members
|
|
74
|
+
memberSymbol.flags |= OutputSymbolFlags.InstanceMember;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Propagate the name after the name policy was applied
|
|
78
|
+
const updatedProps: DeclarationProps = {
|
|
79
|
+
...props,
|
|
80
|
+
name: sym.name,
|
|
81
|
+
nameKind: "class",
|
|
82
|
+
};
|
|
83
|
+
const hasChildren =
|
|
84
|
+
childrenArray(() => props.children).filter((c) => Boolean(c)).length > 0;
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Declaration symbol={sym}>
|
|
88
|
+
class <Name />
|
|
89
|
+
<Scope name={updatedProps.name} kind="class">
|
|
90
|
+
{basesPart}
|
|
91
|
+
<PythonBlock opener=":">
|
|
92
|
+
<Show when={Boolean(props.doc)}>{props.doc}</Show>
|
|
93
|
+
{hasChildren ? props.children : "pass"}
|
|
94
|
+
</PythonBlock>
|
|
95
|
+
</Scope>
|
|
96
|
+
</Declaration>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
emitSymbol,
|
|
3
|
+
instantiateTakenMembersTo as instantiateTakenSymbolsTo,
|
|
4
|
+
OutputSymbolFlags,
|
|
5
|
+
useContext,
|
|
6
|
+
} from "@alloy-js/core";
|
|
7
|
+
import { createPythonSymbol } from "../symbol-creation.js";
|
|
8
|
+
import {
|
|
9
|
+
FunctionCallExpression,
|
|
10
|
+
FunctionCallExpressionProps,
|
|
11
|
+
} from "./FunctionCallExpression.jsx";
|
|
12
|
+
import { PythonSourceFileContext } from "./SourceFile.jsx";
|
|
13
|
+
|
|
14
|
+
export interface ClassInstantiationProps extends FunctionCallExpressionProps {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Used to create new instances of classes in Python.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <ClassInstantiation target="MyClass" args={["arg1", "arg2"]} />
|
|
22
|
+
* ```
|
|
23
|
+
* This will generate:
|
|
24
|
+
* ```python
|
|
25
|
+
* MyClass(arg1, arg2)
|
|
26
|
+
* ```
|
|
27
|
+
* @remarks
|
|
28
|
+
*
|
|
29
|
+
* It is similar to FunctionCallExpression but specifically for class instantiation.
|
|
30
|
+
* Args should be a list arguments that can be either simple js values or py.Atoms, which will render as positional arguments,
|
|
31
|
+
* or py.VariableDeclarations, which will render as named arguments in the call statement. This component will
|
|
32
|
+
* not check for the correctness of the python grammar and will just work with any children you provide.
|
|
33
|
+
* It is up to you to ensure that the arguments you provide are valid in the context of a class instantiation.
|
|
34
|
+
*/
|
|
35
|
+
export function ClassInstantiation(props: ClassInstantiationProps) {
|
|
36
|
+
const sfContext = useContext(PythonSourceFileContext);
|
|
37
|
+
const module = sfContext?.module;
|
|
38
|
+
const sym = createPythonSymbol(
|
|
39
|
+
"",
|
|
40
|
+
{
|
|
41
|
+
flags: OutputSymbolFlags.Transient,
|
|
42
|
+
module: module,
|
|
43
|
+
},
|
|
44
|
+
undefined,
|
|
45
|
+
false,
|
|
46
|
+
);
|
|
47
|
+
instantiateTakenSymbolsTo(sym);
|
|
48
|
+
emitSymbol(sym);
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
<FunctionCallExpression {...props} />
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
Declaration as CoreDeclaration,
|
|
4
|
+
MemberScope,
|
|
5
|
+
OutputSymbolFlags,
|
|
6
|
+
Refkey,
|
|
7
|
+
} from "@alloy-js/core";
|
|
8
|
+
import { PythonElements } from "../name-policy.js";
|
|
9
|
+
import { createPythonSymbol } from "../symbol-creation.js";
|
|
10
|
+
import { PythonOutputSymbol } from "../symbols/index.js";
|
|
11
|
+
|
|
12
|
+
export interface BaseDeclarationProps {
|
|
13
|
+
/**
|
|
14
|
+
* The base name of this declaration. May change depending on naming policy
|
|
15
|
+
* and any conflicts.
|
|
16
|
+
*/
|
|
17
|
+
name: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The refkey or array of refkeys for this declaration.
|
|
21
|
+
*/
|
|
22
|
+
refkey?: Refkey | Refkey[];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Flags for the symbol created by this component.
|
|
26
|
+
*/
|
|
27
|
+
flags?: OutputSymbolFlags;
|
|
28
|
+
|
|
29
|
+
children?: Children;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Documentation for this declaration
|
|
33
|
+
*/
|
|
34
|
+
doc?: Children;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface DeclarationProps extends Omit<BaseDeclarationProps, "name"> {
|
|
38
|
+
/**
|
|
39
|
+
* The name of this declaration.
|
|
40
|
+
*/
|
|
41
|
+
name?: string;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The name policy kind to apply to the declaration.
|
|
45
|
+
*/
|
|
46
|
+
nameKind?: PythonElements;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The symbol to use for this declaration.
|
|
50
|
+
*/
|
|
51
|
+
symbol?: PythonOutputSymbol;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A Python declaration, which can be a class, function, variable, etc.
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* This component is used to create a declaration with a symbol that can be
|
|
59
|
+
* referenced in the code. It can also be used to create a member scope for
|
|
60
|
+
* member containers.
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
export function Declaration(props: DeclarationProps) {
|
|
64
|
+
let sym: PythonOutputSymbol;
|
|
65
|
+
|
|
66
|
+
if (props.symbol) {
|
|
67
|
+
sym = props.symbol;
|
|
68
|
+
} else {
|
|
69
|
+
sym = createPythonSymbol(
|
|
70
|
+
props.name!,
|
|
71
|
+
{
|
|
72
|
+
refkeys: props.refkey,
|
|
73
|
+
flags: props.flags,
|
|
74
|
+
},
|
|
75
|
+
props.nameKind!,
|
|
76
|
+
true,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function withMemberScope(children: Children) {
|
|
81
|
+
return <MemberScope owner={sym}>{children}</MemberScope>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let children: Children = () => props.children;
|
|
85
|
+
|
|
86
|
+
if (sym.flags & OutputSymbolFlags.MemberContainer) {
|
|
87
|
+
children = withMemberScope(children);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return <CoreDeclaration symbol={sym}>{children}</CoreDeclaration>;
|
|
91
|
+
}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
Declaration as CoreDeclaration,
|
|
4
|
+
For,
|
|
5
|
+
MemberScope,
|
|
6
|
+
OutputSymbolFlags,
|
|
7
|
+
Scope,
|
|
8
|
+
Show,
|
|
9
|
+
useBinder,
|
|
10
|
+
} from "@alloy-js/core";
|
|
11
|
+
import { enumModule } from "../builtins/python.js";
|
|
12
|
+
import { createPythonSymbol } from "../symbol-creation.js";
|
|
13
|
+
import { usePythonScope } from "../symbols/scopes.js";
|
|
14
|
+
import { BaseDeclarationProps } from "./Declaration.js";
|
|
15
|
+
import { EnumMember } from "./EnumMember.js";
|
|
16
|
+
import { PythonBlock } from "./PythonBlock.jsx";
|
|
17
|
+
import { SimpleCommentBlock } from "./index.js";
|
|
18
|
+
|
|
19
|
+
export interface EnumProps extends BaseDeclarationProps {
|
|
20
|
+
/**
|
|
21
|
+
* The base type of the enum. One of: 'Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag'.
|
|
22
|
+
* Defaults to 'Enum'.
|
|
23
|
+
*/
|
|
24
|
+
baseType?: "Enum" | "IntEnum" | "StrEnum" | "Flag" | "IntFlag";
|
|
25
|
+
/**
|
|
26
|
+
* Members of the enum as an array of objects.
|
|
27
|
+
*/
|
|
28
|
+
members?: Array<{
|
|
29
|
+
name: string;
|
|
30
|
+
value?: Children;
|
|
31
|
+
jsValue?: string | number;
|
|
32
|
+
doc?: string;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* The enum style: 'classic' (default), 'auto', or 'functional'.
|
|
36
|
+
*/
|
|
37
|
+
style?: "classic" | "auto" | "functional";
|
|
38
|
+
/**
|
|
39
|
+
* Optional docstring for the enum.
|
|
40
|
+
*/
|
|
41
|
+
doc?: Children;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A Python enum declaration, following https://docs.python.org/3.11/library/enum.html.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <EnumDeclaration name="Direction" style="functional">
|
|
50
|
+
* members={[
|
|
51
|
+
* { name: "NORTH" },
|
|
52
|
+
* { name: "SOUTH" },
|
|
53
|
+
* { name: "EAST" },
|
|
54
|
+
* { name: "WEST" },
|
|
55
|
+
* ]}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
* This will generate:
|
|
59
|
+
* ```python
|
|
60
|
+
* from enum import Enum
|
|
61
|
+
* class Direction(Enum):
|
|
62
|
+
* NORTH = "NORTH"
|
|
63
|
+
* SOUTH = "SOUTH"
|
|
64
|
+
* EAST = "EAST"
|
|
65
|
+
* WEST = "WEST"
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function EnumDeclaration(props: EnumProps) {
|
|
69
|
+
// Handle enum styles
|
|
70
|
+
if (props.style === "functional") {
|
|
71
|
+
return <FunctionalEnumDeclaration {...props} />;
|
|
72
|
+
}
|
|
73
|
+
return <ClassEnumDeclaration {...props} />;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create a Python enum using the functional syntax.
|
|
78
|
+
*
|
|
79
|
+
* This generates enums using the `Enum('Name', [...])` or `Enum('Name', {...})` syntax.
|
|
80
|
+
* The format depends on whether enum members have explicit values:
|
|
81
|
+
* - Members without values: `Enum('Direction', ['NORTH', 'SOUTH', 'EAST', 'WEST'])`
|
|
82
|
+
* - Members with values: `Enum('Direction', {'NORTH': 1, 'SOUTH': 2, 'EAST': 3, 'WEST': 4})`
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```tsx
|
|
86
|
+
* <FunctionalEnumDeclaration
|
|
87
|
+
* name="Direction"
|
|
88
|
+
* members={[
|
|
89
|
+
* { name: "NORTH" },
|
|
90
|
+
* { name: "SOUTH" },
|
|
91
|
+
* { name: "EAST" },
|
|
92
|
+
* { name: "WEST" }
|
|
93
|
+
* ]}
|
|
94
|
+
* />
|
|
95
|
+
* ```
|
|
96
|
+
* renders to:
|
|
97
|
+
* ```python
|
|
98
|
+
* Direction = Enum('Direction', ['NORTH', 'SOUTH', 'EAST', 'WEST'])
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```tsx
|
|
103
|
+
* <FunctionalEnumDeclaration
|
|
104
|
+
* name="Status"
|
|
105
|
+
* members={[
|
|
106
|
+
* { name: "PENDING", value: 1 },
|
|
107
|
+
* { name: "ACTIVE", value: 2 },
|
|
108
|
+
* { name: "INACTIVE", value: 3 }
|
|
109
|
+
* ]}
|
|
110
|
+
* />
|
|
111
|
+
* ```
|
|
112
|
+
* renders to:
|
|
113
|
+
* ```python
|
|
114
|
+
* Status = Enum('Status', {'PENDING': 1, 'ACTIVE': 2, 'INACTIVE': 3})
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export function FunctionalEnumDeclaration(props: EnumProps) {
|
|
118
|
+
const binder = useBinder();
|
|
119
|
+
const scope = usePythonScope();
|
|
120
|
+
const sym = createPythonSymbol(
|
|
121
|
+
props.name,
|
|
122
|
+
{
|
|
123
|
+
binder: binder,
|
|
124
|
+
scope: scope,
|
|
125
|
+
refkeys: props.refkey,
|
|
126
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
127
|
+
},
|
|
128
|
+
"enum",
|
|
129
|
+
false,
|
|
130
|
+
);
|
|
131
|
+
const members = props.members ?? [];
|
|
132
|
+
let opener, ender;
|
|
133
|
+
if (members.length && members.every((m) => m.value === undefined)) {
|
|
134
|
+
// List of names: Enum('Direction', ['NORTH', ...])
|
|
135
|
+
opener = "[";
|
|
136
|
+
ender = "]";
|
|
137
|
+
} else {
|
|
138
|
+
// List of name-value pairs: Enum('Direction', {'NORTH': 1, ...})
|
|
139
|
+
opener = "{";
|
|
140
|
+
ender = "}";
|
|
141
|
+
}
|
|
142
|
+
const memberExpr = (
|
|
143
|
+
<>
|
|
144
|
+
{opener}
|
|
145
|
+
<For each={members} joiner=", ">
|
|
146
|
+
{(m) => <EnumMember name={m.name} value={m.value} functional={true} />}
|
|
147
|
+
</For>
|
|
148
|
+
{ender}
|
|
149
|
+
</>
|
|
150
|
+
);
|
|
151
|
+
return (
|
|
152
|
+
<>
|
|
153
|
+
<CoreDeclaration symbol={sym}>
|
|
154
|
+
{sym.name} = {enumModule["."].Enum}('{sym.name}',{" "}
|
|
155
|
+
<MemberScope owner={sym}>
|
|
156
|
+
<Scope name={props.name} kind="enum">
|
|
157
|
+
{memberExpr}
|
|
158
|
+
</Scope>
|
|
159
|
+
</MemberScope>
|
|
160
|
+
)
|
|
161
|
+
</CoreDeclaration>
|
|
162
|
+
</>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Create a Python enum using the class-based syntax.
|
|
168
|
+
*
|
|
169
|
+
* This generates enums using the `class Name(Enum):` syntax with member definitions
|
|
170
|
+
* inside the class body. Supports various member value styles including auto-generated
|
|
171
|
+
* values, explicit values, and custom base types.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```tsx
|
|
175
|
+
* <ClassEnumDeclaration
|
|
176
|
+
* name="Direction"
|
|
177
|
+
* members={[
|
|
178
|
+
* { name: "NORTH" },
|
|
179
|
+
* { name: "SOUTH" },
|
|
180
|
+
* { name: "EAST" },
|
|
181
|
+
* { name: "WEST" }
|
|
182
|
+
* ]}
|
|
183
|
+
* />
|
|
184
|
+
* ```
|
|
185
|
+
* renders to:
|
|
186
|
+
* ```python
|
|
187
|
+
* class Direction(Enum):
|
|
188
|
+
* NORTH = "NORTH"
|
|
189
|
+
* SOUTH = "SOUTH"
|
|
190
|
+
* EAST = "EAST"
|
|
191
|
+
* WEST = "WEST"
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* With explicit values:
|
|
196
|
+
* ```tsx
|
|
197
|
+
* <ClassEnumDeclaration
|
|
198
|
+
* name="Status"
|
|
199
|
+
* members={[
|
|
200
|
+
* { name: "PENDING", value: 1 },
|
|
201
|
+
* { name: "ACTIVE", value: 2 },
|
|
202
|
+
* { name: "INACTIVE", value: 3 }
|
|
203
|
+
* ]}
|
|
204
|
+
* />
|
|
205
|
+
* ```
|
|
206
|
+
* renders to:
|
|
207
|
+
* ```python
|
|
208
|
+
* class Status(Enum):
|
|
209
|
+
* PENDING = 1
|
|
210
|
+
* ACTIVE = 2
|
|
211
|
+
* INACTIVE = 3
|
|
212
|
+
* ```
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* With auto() values:
|
|
216
|
+
* ```tsx
|
|
217
|
+
* <ClassEnumDeclaration
|
|
218
|
+
* name="Color"
|
|
219
|
+
* style="auto"
|
|
220
|
+
* members={[
|
|
221
|
+
* { name: "RED" },
|
|
222
|
+
* { name: "GREEN" },
|
|
223
|
+
* { name: "BLUE" }
|
|
224
|
+
* ]}
|
|
225
|
+
* />
|
|
226
|
+
* ```
|
|
227
|
+
* renders to:
|
|
228
|
+
* ```python
|
|
229
|
+
* class Color(Enum):
|
|
230
|
+
* RED = auto()
|
|
231
|
+
* GREEN = auto()
|
|
232
|
+
* BLUE = auto()
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export function ClassEnumDeclaration(props: EnumProps) {
|
|
236
|
+
const baseType = props.baseType || "Enum";
|
|
237
|
+
const binder = useBinder();
|
|
238
|
+
const scope = usePythonScope();
|
|
239
|
+
const sym = createPythonSymbol(
|
|
240
|
+
props.name,
|
|
241
|
+
{
|
|
242
|
+
binder: binder,
|
|
243
|
+
scope: scope,
|
|
244
|
+
refkeys: props.refkey,
|
|
245
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
246
|
+
},
|
|
247
|
+
"enum",
|
|
248
|
+
false,
|
|
249
|
+
);
|
|
250
|
+
let memberList: Array<{
|
|
251
|
+
name: string;
|
|
252
|
+
value?: Children;
|
|
253
|
+
jsValue?: string | number;
|
|
254
|
+
auto?: boolean;
|
|
255
|
+
doc?: string;
|
|
256
|
+
}> = (props.members ?? []).map((m) =>
|
|
257
|
+
m.value === undefined ? { ...m, auto: false } : m,
|
|
258
|
+
);
|
|
259
|
+
if (props.style === "auto") {
|
|
260
|
+
memberList = memberList.map((m) =>
|
|
261
|
+
m.value === undefined ? { name: m.name, auto: true } : m,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
return (
|
|
265
|
+
<CoreDeclaration symbol={sym}>
|
|
266
|
+
<Show when={Boolean(props.doc)}>
|
|
267
|
+
<SimpleCommentBlock children={props.doc} />
|
|
268
|
+
<hbr />
|
|
269
|
+
</Show>
|
|
270
|
+
class {sym.name}({enumModule["."][baseType]})
|
|
271
|
+
<MemberScope owner={sym}>
|
|
272
|
+
<Scope name={sym.name} kind="enum">
|
|
273
|
+
<PythonBlock opener=":">
|
|
274
|
+
<For each={memberList} hardline>
|
|
275
|
+
{(member) => (
|
|
276
|
+
<EnumMember
|
|
277
|
+
name={member.name}
|
|
278
|
+
value={member.value}
|
|
279
|
+
jsValue={member.jsValue}
|
|
280
|
+
auto={member.auto}
|
|
281
|
+
doc={member.doc}
|
|
282
|
+
/>
|
|
283
|
+
)}
|
|
284
|
+
</For>
|
|
285
|
+
{props.children}
|
|
286
|
+
</PythonBlock>
|
|
287
|
+
</Scope>
|
|
288
|
+
</MemberScope>
|
|
289
|
+
</CoreDeclaration>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Children, OutputSymbolFlags, Refkey, Show } from "@alloy-js/core";
|
|
2
|
+
import { enumModule } from "../builtins/python.js";
|
|
3
|
+
import { createPythonSymbol } from "../symbol-creation.js";
|
|
4
|
+
import { PythonOutputSymbol } from "../symbols/index.js";
|
|
5
|
+
import { Atom } from "./Atom.jsx";
|
|
6
|
+
import { SimpleInlineComment } from "./index.js";
|
|
7
|
+
|
|
8
|
+
export interface EnumMemberProps {
|
|
9
|
+
/**
|
|
10
|
+
* The name of the enum member.
|
|
11
|
+
*/
|
|
12
|
+
name: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Refkey for the enum member symbol. If the refkey is not provided, a symbol
|
|
16
|
+
* will be created and the member cannot be referenced by refkey.
|
|
17
|
+
*/
|
|
18
|
+
refkey?: Refkey;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The value of the enum member.
|
|
22
|
+
*/
|
|
23
|
+
value?: Children;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The JS value of the enum member.
|
|
27
|
+
*/
|
|
28
|
+
jsValue?: string | number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Functional mappings/list
|
|
32
|
+
*/
|
|
33
|
+
functional?: boolean;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Will use auto() to generate the value if set to true.
|
|
37
|
+
*/
|
|
38
|
+
auto?: boolean;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Documentation for the enum member.
|
|
42
|
+
*/
|
|
43
|
+
doc?: Children;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A Python enum member.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* <EnumMember name="NORTH" />
|
|
52
|
+
* ```
|
|
53
|
+
* This will generate:
|
|
54
|
+
* ```python
|
|
55
|
+
* NORTH
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function EnumMember(props: EnumMemberProps) {
|
|
59
|
+
const autoReference = props.auto === true ? enumModule["."].auto : undefined;
|
|
60
|
+
const value = props.auto === true ? <>{autoReference}()</> : props.value;
|
|
61
|
+
const sym: PythonOutputSymbol = createPythonSymbol(
|
|
62
|
+
props.name,
|
|
63
|
+
{
|
|
64
|
+
refkeys: props.refkey,
|
|
65
|
+
flags: OutputSymbolFlags.StaticMember,
|
|
66
|
+
},
|
|
67
|
+
"enum-member",
|
|
68
|
+
true,
|
|
69
|
+
);
|
|
70
|
+
const valueCode =
|
|
71
|
+
props.jsValue !== undefined ? <Atom jsValue={props.jsValue} /> : value;
|
|
72
|
+
|
|
73
|
+
if (props.functional) {
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
'{sym.name}'<Show when={valueCode !== undefined}> : {valueCode}</Show>
|
|
77
|
+
<Show when={props.doc !== undefined}>
|
|
78
|
+
<SimpleInlineComment>{props.doc}</SimpleInlineComment>
|
|
79
|
+
</Show>
|
|
80
|
+
</>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return (
|
|
84
|
+
<>
|
|
85
|
+
{sym.name}
|
|
86
|
+
<Show when={valueCode !== undefined}> = {valueCode}</Show>
|
|
87
|
+
<Show when={props.doc !== undefined}>
|
|
88
|
+
<SimpleInlineComment>{props.doc}</SimpleInlineComment>
|
|
89
|
+
</Show>
|
|
90
|
+
</>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Children, For, Indent, Wrap } from "@alloy-js/core";
|
|
2
|
+
|
|
3
|
+
export interface FunctionCallExpressionProps {
|
|
4
|
+
target: Children;
|
|
5
|
+
args?: Children[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A Python function call expression.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <FunctionCallExpression target="foo" args={["arg1", "arg2"]} />
|
|
14
|
+
* ```
|
|
15
|
+
* This will generate:
|
|
16
|
+
* ```python
|
|
17
|
+
* foo(arg1, arg2)
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function FunctionCallExpression(props: FunctionCallExpressionProps) {
|
|
21
|
+
return (
|
|
22
|
+
<group>
|
|
23
|
+
{props.target}(
|
|
24
|
+
<Wrap
|
|
25
|
+
when={!!props.args && props.args.length > 1}
|
|
26
|
+
with={Indent}
|
|
27
|
+
props={{ softline: true, trailingBreak: true }}
|
|
28
|
+
>
|
|
29
|
+
<For each={props.args ?? []} comma line>
|
|
30
|
+
{(arg) => arg}
|
|
31
|
+
</For>
|
|
32
|
+
</Wrap>
|
|
33
|
+
)
|
|
34
|
+
</group>
|
|
35
|
+
);
|
|
36
|
+
}
|