@typespec/emitter-framework 0.15.0-dev.2 → 0.15.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.
- package/CHANGELOG.md +1 -16
- package/dist/src/core/components/overrides/component-overrides.d.ts.map +1 -1
- package/dist/src/core/components/overrides/component-overrides.js.map +1 -1
- package/dist/src/python/builtins.d.ts +14 -0
- package/dist/src/python/builtins.d.ts.map +1 -0
- package/dist/src/python/builtins.js +29 -0
- package/dist/src/python/builtins.js.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.d.ts +6 -0
- package/dist/src/python/components/array-expression/array-expression.d.ts.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.js +11 -0
- package/dist/src/python/components/array-expression/array-expression.js.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.test.d.ts +2 -0
- package/dist/src/python/components/array-expression/array-expression.test.d.ts.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.test.js +19 -0
- package/dist/src/python/components/array-expression/array-expression.test.js.map +1 -0
- package/dist/src/python/components/array-expression/index.d.ts +2 -0
- package/dist/src/python/components/array-expression/index.d.ts.map +1 -0
- package/dist/src/python/components/array-expression/index.js +2 -0
- package/dist/src/python/components/array-expression/index.js.map +1 -0
- package/dist/src/python/components/atom/atom.d.ts +33 -0
- package/dist/src/python/components/atom/atom.d.ts.map +1 -0
- package/dist/src/python/components/atom/atom.js +88 -0
- package/dist/src/python/components/atom/atom.js.map +1 -0
- package/dist/src/python/components/atom/atom.test.d.ts +2 -0
- package/dist/src/python/components/atom/atom.test.d.ts.map +1 -0
- package/dist/src/python/components/atom/atom.test.js +224 -0
- package/dist/src/python/components/atom/atom.test.js.map +1 -0
- package/dist/src/python/components/atom/index.d.ts +2 -0
- package/dist/src/python/components/atom/index.d.ts.map +1 -0
- package/dist/src/python/components/atom/index.js +2 -0
- package/dist/src/python/components/atom/index.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-bases.d.ts +45 -0
- package/dist/src/python/components/class-declaration/class-bases.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-bases.js +84 -0
- package/dist/src/python/components/class-declaration/class-bases.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-body.d.ts +16 -0
- package/dist/src/python/components/class-declaration/class-body.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-body.js +52 -0
- package/dist/src/python/components/class-declaration/class-body.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.d.ts +23 -0
- package/dist/src/python/components/class-declaration/class-declaration.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.js +118 -0
- package/dist/src/python/components/class-declaration/class-declaration.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.d.ts +2 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.js +1527 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.d.ts +16 -0
- package/dist/src/python/components/class-declaration/class-member.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.js +71 -0
- package/dist/src/python/components/class-declaration/class-member.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.test.d.ts +2 -0
- package/dist/src/python/components/class-declaration/class-member.test.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.test.js +202 -0
- package/dist/src/python/components/class-declaration/class-member.test.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.d.ts +22 -0
- package/dist/src/python/components/class-declaration/class-method.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.js +76 -0
- package/dist/src/python/components/class-declaration/class-method.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.test.d.ts +2 -0
- package/dist/src/python/components/class-declaration/class-method.test.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.test.js +298 -0
- package/dist/src/python/components/class-declaration/class-method.test.js.map +1 -0
- package/dist/src/python/components/class-declaration/index.d.ts +7 -0
- package/dist/src/python/components/class-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/index.js +7 -0
- package/dist/src/python/components/class-declaration/index.js.map +1 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.d.ts +22 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.js +67 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.js.map +1 -0
- package/dist/src/python/components/doc-element/doc-element.d.ts +46 -0
- package/dist/src/python/components/doc-element/doc-element.d.ts.map +1 -0
- package/dist/src/python/components/doc-element/doc-element.js +59 -0
- package/dist/src/python/components/doc-element/doc-element.js.map +1 -0
- package/dist/src/python/components/doc-element/index.d.ts +2 -0
- package/dist/src/python/components/doc-element/index.d.ts.map +1 -0
- package/dist/src/python/components/doc-element/index.js +2 -0
- package/dist/src/python/components/doc-element/index.js.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.d.ts +8 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.js +80 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.js.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts +2 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.js +344 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.js.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-member.d.ts +9 -0
- package/dist/src/python/components/enum-declaration/enum-member.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-member.js +22 -0
- package/dist/src/python/components/enum-declaration/enum-member.js.map +1 -0
- package/dist/src/python/components/enum-declaration/index.d.ts +3 -0
- package/dist/src/python/components/enum-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/index.js +3 -0
- package/dist/src/python/components/enum-declaration/index.js.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.d.ts +24 -0
- package/dist/src/python/components/function-declaration/function-declaration.d.ts.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.js +68 -0
- package/dist/src/python/components/function-declaration/function-declaration.js.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.d.ts +2 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.js +682 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.js.map +1 -0
- package/dist/src/python/components/function-declaration/index.d.ts +2 -0
- package/dist/src/python/components/function-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/function-declaration/index.js +2 -0
- package/dist/src/python/components/function-declaration/index.js.map +1 -0
- package/dist/src/python/components/index.d.ts +12 -0
- package/dist/src/python/components/index.d.ts.map +1 -0
- package/dist/src/python/components/index.js +12 -0
- package/dist/src/python/components/index.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts +25 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.js +33 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/index.d.ts +3 -0
- package/dist/src/python/components/protocol-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/index.js +3 -0
- package/dist/src/python/components/protocol-declaration/index.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts +8 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.js +86 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts +2 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js +117 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js.map +1 -0
- package/dist/src/python/components/record-expression/index.d.ts +2 -0
- package/dist/src/python/components/record-expression/index.d.ts.map +1 -0
- package/dist/src/python/components/record-expression/index.js +2 -0
- package/dist/src/python/components/record-expression/index.js.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.d.ts +6 -0
- package/dist/src/python/components/record-expression/record-expression.d.ts.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.js +13 -0
- package/dist/src/python/components/record-expression/record-expression.js.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.test.d.ts +2 -0
- package/dist/src/python/components/record-expression/record-expression.test.d.ts.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.test.js +19 -0
- package/dist/src/python/components/record-expression/record-expression.test.js.map +1 -0
- package/dist/src/python/components/type-alias-declaration/index.d.ts +2 -0
- package/dist/src/python/components/type-alias-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/type-alias-declaration/index.js +2 -0
- package/dist/src/python/components/type-alias-declaration/index.js.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts +16 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js +75 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts +2 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js +140 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js.map +1 -0
- package/dist/src/python/components/type-declaration/index.d.ts +2 -0
- package/dist/src/python/components/type-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/type-declaration/index.js +2 -0
- package/dist/src/python/components/type-declaration/index.js.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.d.ts +11 -0
- package/dist/src/python/components/type-declaration/type-declaration.d.ts.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.js +31 -0
- package/dist/src/python/components/type-declaration/type-declaration.js.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.d.ts +2 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.js +69 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.js.map +1 -0
- package/dist/src/python/components/type-expression/index.d.ts +2 -0
- package/dist/src/python/components/type-expression/index.d.ts.map +1 -0
- package/dist/src/python/components/type-expression/index.js +2 -0
- package/dist/src/python/components/type-expression/index.js.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.d.ts +12 -0
- package/dist/src/python/components/type-expression/type-expression.d.ts.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.js +348 -0
- package/dist/src/python/components/type-expression/type-expression.js.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.test.d.ts +2 -0
- package/dist/src/python/components/type-expression/type-expression.test.d.ts.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.test.js +503 -0
- package/dist/src/python/components/type-expression/type-expression.test.js.map +1 -0
- package/dist/src/python/index.d.ts +4 -0
- package/dist/src/python/index.d.ts.map +1 -0
- package/dist/src/python/index.js +4 -0
- package/dist/src/python/index.js.map +1 -0
- package/dist/src/python/lib.d.ts +68 -0
- package/dist/src/python/lib.d.ts.map +1 -0
- package/dist/src/python/lib.js +38 -0
- package/dist/src/python/lib.js.map +1 -0
- package/dist/src/python/test-utils.d.ts +8 -0
- package/dist/src/python/test-utils.d.ts.map +1 -0
- package/dist/src/python/test-utils.js +25 -0
- package/dist/src/python/test-utils.js.map +1 -0
- package/dist/src/python/utils/index.d.ts +4 -0
- package/dist/src/python/utils/index.d.ts.map +1 -0
- package/dist/src/python/utils/index.js +4 -0
- package/dist/src/python/utils/index.js.map +1 -0
- package/dist/src/python/utils/operation.d.ts +27 -0
- package/dist/src/python/utils/operation.d.ts.map +1 -0
- package/dist/src/python/utils/operation.js +139 -0
- package/dist/src/python/utils/operation.js.map +1 -0
- package/dist/src/python/utils/refkey.d.ts +23 -0
- package/dist/src/python/utils/refkey.d.ts.map +1 -0
- package/dist/src/python/utils/refkey.js +36 -0
- package/dist/src/python/utils/refkey.js.map +1 -0
- package/dist/src/python/utils/type.d.ts +19 -0
- package/dist/src/python/utils/type.d.ts.map +1 -0
- package/dist/src/python/utils/type.js +24 -0
- package/dist/src/python/utils/type.js.map +1 -0
- package/dist/src/typescript/components/function-declaration.d.ts.map +1 -1
- package/dist/src/typescript/components/function-declaration.js.map +1 -1
- package/package.json +12 -4
- package/package.json.bak +13 -4
- package/src/core/components/overrides/component-overrides.tsx +9 -6
- package/src/python/builtins.ts +43 -0
- package/src/python/components/array-expression/array-expression.test.tsx +14 -0
- package/src/python/components/array-expression/array-expression.tsx +11 -0
- package/src/python/components/array-expression/index.ts +1 -0
- package/src/python/components/atom/atom.test.tsx +244 -0
- package/src/python/components/atom/atom.tsx +95 -0
- package/src/python/components/atom/index.ts +1 -0
- package/src/python/components/class-declaration/class-bases.tsx +92 -0
- package/src/python/components/class-declaration/class-body.tsx +56 -0
- package/src/python/components/class-declaration/class-declaration.test.tsx +1414 -0
- package/src/python/components/class-declaration/class-declaration.tsx +116 -0
- package/src/python/components/class-declaration/class-member.test.tsx +194 -0
- package/src/python/components/class-declaration/class-member.tsx +67 -0
- package/src/python/components/class-declaration/class-method.test.tsx +250 -0
- package/src/python/components/class-declaration/class-method.tsx +97 -0
- package/src/python/components/class-declaration/index.ts +6 -0
- package/src/python/components/class-declaration/primitive-initializer.tsx +62 -0
- package/src/python/components/doc-element/doc-element.tsx +83 -0
- package/src/python/components/doc-element/index.ts +1 -0
- package/src/python/components/enum-declaration/enum-declaration.test.tsx +319 -0
- package/src/python/components/enum-declaration/enum-declaration.tsx +77 -0
- package/src/python/components/enum-declaration/enum-member.tsx +21 -0
- package/src/python/components/enum-declaration/index.ts +2 -0
- package/src/python/components/function-declaration/function-declaration.test.tsx +582 -0
- package/src/python/components/function-declaration/function-declaration.tsx +90 -0
- package/src/python/components/function-declaration/index.ts +1 -0
- package/src/python/components/index.ts +11 -0
- package/src/python/components/protocol-declaration/callable-parameters.tsx +44 -0
- package/src/python/components/protocol-declaration/index.ts +2 -0
- package/src/python/components/protocol-declaration/protocol-declaration.test.tsx +106 -0
- package/src/python/components/protocol-declaration/protocol-declaration.tsx +73 -0
- package/src/python/components/record-expression/index.ts +1 -0
- package/src/python/components/record-expression/record-expression.test.tsx +14 -0
- package/src/python/components/record-expression/record-expression.tsx +13 -0
- package/src/python/components/type-alias-declaration/index.ts +1 -0
- package/src/python/components/type-alias-declaration/type-alias-declaration.test.tsx +117 -0
- package/src/python/components/type-alias-declaration/type-alias-declaration.tsx +67 -0
- package/src/python/components/type-declaration/index.ts +1 -0
- package/src/python/components/type-declaration/type-declaration.test.tsx +58 -0
- package/src/python/components/type-declaration/type-declaration.tsx +26 -0
- package/src/python/components/type-expression/index.ts +1 -0
- package/src/python/components/type-expression/type-expression.test.tsx +463 -0
- package/src/python/components/type-expression/type-expression.tsx +333 -0
- package/src/python/index.ts +3 -0
- package/src/python/lib.ts +40 -0
- package/src/python/test-utils.tsx +31 -0
- package/src/python/utils/index.ts +3 -0
- package/src/python/utils/operation.ts +161 -0
- package/src/python/utils/refkey.ts +36 -0
- package/src/python/utils/type.ts +31 -0
- package/src/typescript/components/function-declaration.tsx +4 -2
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { refkey } from "@alloy-js/core";
|
|
2
|
+
import * as py from "@alloy-js/python";
|
|
3
|
+
import type { Operation } from "@typespec/compiler";
|
|
4
|
+
import { useTsp } from "../../../core/context/tsp-context.js";
|
|
5
|
+
import { buildParameterDescriptor } from "../../utils/operation.js";
|
|
6
|
+
|
|
7
|
+
export interface CallableParametersProps {
|
|
8
|
+
/**
|
|
9
|
+
* The operation to extract parameters from.
|
|
10
|
+
*/
|
|
11
|
+
type: Operation;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Builds parameter descriptors for a callable (method/function) from an Operation's parameters.
|
|
16
|
+
*
|
|
17
|
+
* Iterates over the operation's parameters model and creates ParameterDescriptor objects
|
|
18
|
+
* with name, type expression, and default value (handles both explicit defaults and
|
|
19
|
+
* optional parameters without defaults which get `= None`).
|
|
20
|
+
*
|
|
21
|
+
* @returns Array of ParameterDescriptor objects for use with py.MethodDeclaration or similar.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* const params = CallableParameters({ type: operation });
|
|
26
|
+
* <py.MethodDeclaration name="foo" parameters={params} />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function CallableParameters(props: CallableParametersProps): py.ParameterDescriptor[] {
|
|
30
|
+
const { $ } = useTsp();
|
|
31
|
+
const paramsModel = props.type.parameters;
|
|
32
|
+
|
|
33
|
+
if (!paramsModel) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const parameters: py.ParameterDescriptor[] = [];
|
|
38
|
+
|
|
39
|
+
for (const prop of $.model.getProperties(paramsModel).values()) {
|
|
40
|
+
parameters.push(buildParameterDescriptor(prop, refkey()));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return parameters;
|
|
44
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { TypeExpression } from "#python/components/type-expression/type-expression.js";
|
|
2
|
+
import { Tester } from "#test/test-host.js";
|
|
3
|
+
import { t } from "@typespec/compiler/testing";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { getOutput } from "../../test-utils.js";
|
|
6
|
+
import { ProtocolDeclaration } from "./protocol-declaration.js";
|
|
7
|
+
|
|
8
|
+
describe("Python ProtocolDeclaration", () => {
|
|
9
|
+
it("emits a callback Protocol for an operation", async () => {
|
|
10
|
+
const { program, getName, getOtherName } = await Tester.compile(t.code`
|
|
11
|
+
op ${t.op("getName")}(id: string): string;
|
|
12
|
+
op ${t.op("getOtherName")}(id: string): string;
|
|
13
|
+
`);
|
|
14
|
+
|
|
15
|
+
expect(
|
|
16
|
+
getOutput(program, [
|
|
17
|
+
<ProtocolDeclaration type={getName} />,
|
|
18
|
+
<ProtocolDeclaration type={getOtherName} />,
|
|
19
|
+
]),
|
|
20
|
+
).toRenderTo(`
|
|
21
|
+
from typing import Protocol
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class GetName(Protocol):
|
|
25
|
+
def __call__(self, id: str) -> str:
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class GetOtherName(Protocol):
|
|
31
|
+
def __call__(self, id: str) -> str:
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
`);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("emits no return annotation when return type omitted", async () => {
|
|
39
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
40
|
+
op ${t.op("getName")}(id: string): string;
|
|
41
|
+
`);
|
|
42
|
+
|
|
43
|
+
// Create a shallow clone without returnType to simulate missing return info
|
|
44
|
+
const getNameNoReturn: any = { ...(getName as any) };
|
|
45
|
+
delete getNameNoReturn.returnType;
|
|
46
|
+
|
|
47
|
+
expect(getOutput(program, [<ProtocolDeclaration type={getNameNoReturn} />])).toRenderTo(`
|
|
48
|
+
from typing import Protocol
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class GetName(Protocol):
|
|
52
|
+
def __call__(self, id: str):
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
`);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("emits a Protocol for a TypeSpec interface (methods only)", async () => {
|
|
60
|
+
const { program, Greeter } = await Tester.compile(t.code`
|
|
61
|
+
interface ${t.interface("Greeter")} {
|
|
62
|
+
op getName(id: string): string;
|
|
63
|
+
op getOtherName(id: string): string;
|
|
64
|
+
}
|
|
65
|
+
`);
|
|
66
|
+
|
|
67
|
+
expect(getOutput(program, [<ProtocolDeclaration type={Greeter} />])).toRenderTo(`
|
|
68
|
+
from typing import Protocol
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Greeter(Protocol):
|
|
72
|
+
def get_name(self, id: str) -> str:
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
def get_other_name(self, id: str) -> str:
|
|
76
|
+
...
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
`);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("emits both a Protocol and a Callable for the same operation", async () => {
|
|
83
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
84
|
+
op ${t.op("getName")}(id: string): string;
|
|
85
|
+
`);
|
|
86
|
+
|
|
87
|
+
expect(
|
|
88
|
+
getOutput(program, [
|
|
89
|
+
<ProtocolDeclaration type={getName} />,
|
|
90
|
+
<TypeExpression type={getName} />,
|
|
91
|
+
]),
|
|
92
|
+
).toRenderTo(`
|
|
93
|
+
from typing import Callable
|
|
94
|
+
from typing import Protocol
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class GetName(Protocol):
|
|
98
|
+
def __call__(self, id: str) -> str:
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
Callable[[str], str]
|
|
104
|
+
`);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useTsp } from "#core/context/tsp-context.js";
|
|
2
|
+
import { typingModule } from "#python/builtins.js";
|
|
3
|
+
import { TypeExpression } from "#python/components/type-expression/type-expression.js";
|
|
4
|
+
import { reportPythonDiagnostic } from "#python/lib.js";
|
|
5
|
+
import { declarationRefkeys } from "#python/utils/refkey.js";
|
|
6
|
+
import { mapJoin } from "@alloy-js/core";
|
|
7
|
+
import * as py from "@alloy-js/python";
|
|
8
|
+
import type { Interface, Operation, Type } from "@typespec/compiler";
|
|
9
|
+
import { CallableParameters } from "./callable-parameters.js";
|
|
10
|
+
|
|
11
|
+
export interface ProtocolDeclarationProps extends Omit<py.ClassDeclarationProps, "name"> {
|
|
12
|
+
type: Interface | Operation;
|
|
13
|
+
name?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function ProtocolDeclaration(props: ProtocolDeclarationProps) {
|
|
17
|
+
const { $ } = useTsp();
|
|
18
|
+
|
|
19
|
+
const refkeys = declarationRefkeys(props.refkey, props.type);
|
|
20
|
+
const protocolBase = typingModule["."]["Protocol"];
|
|
21
|
+
|
|
22
|
+
const namePolicy = py.usePythonNamePolicy();
|
|
23
|
+
const originalName = props.name ?? (props.type as any)?.name ?? "";
|
|
24
|
+
const name = namePolicy.getName(originalName, "class");
|
|
25
|
+
|
|
26
|
+
// Interfaces will be converted to Protocols with method stubs for operations
|
|
27
|
+
if ((props.type as any)?.kind === "Interface") {
|
|
28
|
+
const iface = props.type as Interface;
|
|
29
|
+
const operations = ((iface as any).operations ?? new Map()) as Map<string, any>;
|
|
30
|
+
const methods = mapJoin(
|
|
31
|
+
() => Array.from(operations.values()) as any[],
|
|
32
|
+
(op: any) => {
|
|
33
|
+
const methodName = namePolicy.getName(op.name, "function");
|
|
34
|
+
const prm = CallableParameters({ type: op as Operation }); // self injected by MethodDeclaration
|
|
35
|
+
const ret = (op as any)?.returnType ? (
|
|
36
|
+
<TypeExpression type={(op as Operation).returnType as Type} />
|
|
37
|
+
) : undefined;
|
|
38
|
+
return (
|
|
39
|
+
<py.MethodDeclaration name={methodName} parameters={prm} returnType={ret}>
|
|
40
|
+
...
|
|
41
|
+
</py.MethodDeclaration>
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
return (
|
|
46
|
+
<py.ClassDeclaration name={name} bases={[protocolBase]} refkey={refkeys} doc={props.doc}>
|
|
47
|
+
{methods}
|
|
48
|
+
</py.ClassDeclaration>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if ((props.type as any)?.kind !== "Operation") {
|
|
53
|
+
reportPythonDiagnostic($.program, {
|
|
54
|
+
code: "python-unsupported-type",
|
|
55
|
+
target: props.type as any,
|
|
56
|
+
});
|
|
57
|
+
return <></>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Operations will be converted to Callback protocol using a dunder __call__ method
|
|
61
|
+
const op = props.type as Operation;
|
|
62
|
+
const cbParams = CallableParameters({ type: op });
|
|
63
|
+
const cbReturn = (op as any)?.returnType ? (
|
|
64
|
+
<TypeExpression type={op.returnType as Type} />
|
|
65
|
+
) : undefined;
|
|
66
|
+
return (
|
|
67
|
+
<py.ClassDeclaration name={name} bases={[protocolBase]} refkey={refkeys} doc={props.doc}>
|
|
68
|
+
<py.DunderMethodDeclaration name="__call__" returnType={cbReturn} parameters={cbParams}>
|
|
69
|
+
...
|
|
70
|
+
</py.DunderMethodDeclaration>
|
|
71
|
+
</py.ClassDeclaration>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./record-expression.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { d } from "@alloy-js/core/testing";
|
|
3
|
+
import { t } from "@typespec/compiler/testing";
|
|
4
|
+
import { expect, it } from "vitest";
|
|
5
|
+
import { getOutput } from "../../test-utils.js";
|
|
6
|
+
import { TypeExpression } from "../type-expression/type-expression.js";
|
|
7
|
+
|
|
8
|
+
it("maps Record to Python dict", async () => {
|
|
9
|
+
const { program, TestRecord } = await Tester.compile(t.code`
|
|
10
|
+
alias ${t.type("TestRecord")} = Record<boolean>;
|
|
11
|
+
`);
|
|
12
|
+
|
|
13
|
+
expect(getOutput(program, [<TypeExpression type={TestRecord} />])).toRenderTo(d`dict[str, bool]`);
|
|
14
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { code } from "@alloy-js/core";
|
|
2
|
+
import type { Type } from "@typespec/compiler";
|
|
3
|
+
import { TypeExpression } from "../type-expression/type-expression.js";
|
|
4
|
+
|
|
5
|
+
export interface RecordExpressionProps {
|
|
6
|
+
elementType: Type;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function RecordExpression({ elementType }: RecordExpressionProps) {
|
|
10
|
+
return code`
|
|
11
|
+
dict[str, ${(<TypeExpression type={elementType} />)}]
|
|
12
|
+
`;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./type-alias-declaration.js";
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { t } from "@typespec/compiler/testing";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { getOutput } from "../../test-utils.js";
|
|
5
|
+
import { TypeAliasDeclaration } from "./type-alias-declaration.js";
|
|
6
|
+
|
|
7
|
+
describe("Python Declaration equivalency to Type Alias", () => {
|
|
8
|
+
describe("Type Alias Declaration bound to Typespec Scalar", () => {
|
|
9
|
+
describe("Scalar extends utcDateTime", () => {
|
|
10
|
+
it("creates a type alias declaration for a utcDateTime without encoding", async () => {
|
|
11
|
+
const { program, MyDate } = await Tester.compile(t.code`
|
|
12
|
+
scalar ${t.scalar("MyDate")} extends utcDateTime;
|
|
13
|
+
`);
|
|
14
|
+
|
|
15
|
+
expect(getOutput(program, [<TypeAliasDeclaration type={MyDate} />])).toRenderTo(`
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
from typing import TypeAlias
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
my_date: TypeAlias = datetime`);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("creates a type alias declaration with doc", async () => {
|
|
24
|
+
const { program, MyDate } = await Tester.compile(t.code`
|
|
25
|
+
/**
|
|
26
|
+
* Type to represent a date
|
|
27
|
+
*/
|
|
28
|
+
scalar ${t.scalar("MyDate")} extends utcDateTime;
|
|
29
|
+
`);
|
|
30
|
+
|
|
31
|
+
expect(getOutput(program, [<TypeAliasDeclaration type={MyDate} />])).toRenderTo(`
|
|
32
|
+
from datetime import datetime
|
|
33
|
+
from typing import TypeAlias
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Type to represent a date
|
|
37
|
+
my_date: TypeAlias = datetime`);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("can override JSDoc", async () => {
|
|
41
|
+
const { program, MyDate } = await Tester.compile(t.code`
|
|
42
|
+
/**
|
|
43
|
+
* Type to represent a date
|
|
44
|
+
*/
|
|
45
|
+
scalar ${t.scalar("MyDate")} extends utcDateTime;
|
|
46
|
+
`);
|
|
47
|
+
|
|
48
|
+
expect(getOutput(program, [<TypeAliasDeclaration doc={"Overridden Doc"} type={MyDate} />]))
|
|
49
|
+
.toRenderTo(`
|
|
50
|
+
from datetime import datetime
|
|
51
|
+
from typing import TypeAlias
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# Overridden Doc
|
|
55
|
+
my_date: TypeAlias = datetime`);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("creates a type alias declaration for a utcDateTime with unixTimeStamp encoding", async () => {
|
|
59
|
+
const { program, MyDate } = await Tester.compile(t.code`
|
|
60
|
+
@encode("unixTimestamp", int32)
|
|
61
|
+
scalar ${t.scalar("MyDate")} extends utcDateTime;
|
|
62
|
+
`);
|
|
63
|
+
|
|
64
|
+
expect(getOutput(program, [<TypeAliasDeclaration type={MyDate} />])).toRenderTo(`
|
|
65
|
+
from datetime import datetime
|
|
66
|
+
from typing import TypeAlias
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
my_date: TypeAlias = datetime`);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("creates a type alias declaration for a utcDateTime with rfc7231 encoding", async () => {
|
|
73
|
+
const { program, MyDate } = await Tester.compile(t.code`
|
|
74
|
+
@encode("rfc7231")
|
|
75
|
+
scalar ${t.scalar("MyDate")} extends utcDateTime;
|
|
76
|
+
`);
|
|
77
|
+
|
|
78
|
+
expect(getOutput(program, [<TypeAliasDeclaration type={MyDate} />])).toRenderTo(`
|
|
79
|
+
from datetime import datetime
|
|
80
|
+
from typing import TypeAlias
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
my_date: TypeAlias = datetime`);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("creates a type alias declaration for a utcDateTime with rfc3339 encoding", async () => {
|
|
87
|
+
const { program, MyDate } = await Tester.compile(t.code`
|
|
88
|
+
@encode("rfc3339")
|
|
89
|
+
scalar ${t.scalar("MyDate")} extends utcDateTime;
|
|
90
|
+
`);
|
|
91
|
+
|
|
92
|
+
expect(getOutput(program, [<TypeAliasDeclaration type={MyDate} />])).toRenderTo(`
|
|
93
|
+
from datetime import datetime
|
|
94
|
+
from typing import TypeAlias
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
my_date: TypeAlias = datetime`);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("Type Alias Declaration for Operation (Callable)", () => {
|
|
103
|
+
it("creates a type alias for an operation type reference", async () => {
|
|
104
|
+
const { program, Handler } = await Tester.compile(t.code`
|
|
105
|
+
op handleRequest(id: string): string;
|
|
106
|
+
alias ${t.type("Handler")} = handleRequest;
|
|
107
|
+
`);
|
|
108
|
+
|
|
109
|
+
expect(getOutput(program, [<TypeAliasDeclaration type={Handler} />])).toRenderTo(`
|
|
110
|
+
from typing import Callable
|
|
111
|
+
from typing import TypeAlias
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
handle_request: TypeAlias = Callable[[str], str]`);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useTsp } from "#core/context/index.js";
|
|
2
|
+
import * as py from "@alloy-js/python";
|
|
3
|
+
import { isTemplateInstance, type Model, type Type } from "@typespec/compiler";
|
|
4
|
+
import { reportDiagnostic } from "../../../lib.js";
|
|
5
|
+
import { typingModule } from "../../builtins.js";
|
|
6
|
+
import { declarationRefkeys } from "../../utils/refkey.js";
|
|
7
|
+
import { ClassDeclaration } from "../class-declaration/class-declaration.js";
|
|
8
|
+
import { TypeExpression } from "../type-expression/type-expression.js";
|
|
9
|
+
|
|
10
|
+
export interface TypedAliasDeclarationProps extends Omit<py.BaseDeclarationProps, "name"> {
|
|
11
|
+
type: Type;
|
|
12
|
+
name?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create a Python type alias declaration. Pass the `type` prop to emit the
|
|
17
|
+
* type alias as the provided TypeSpec type.
|
|
18
|
+
*
|
|
19
|
+
* For template instances (e.g., `alias StringResponse = Response<string>`),
|
|
20
|
+
* this emits a dataclass instead of a type alias, since Python doesn't support
|
|
21
|
+
* parameterized type aliases the way TypeScript does.
|
|
22
|
+
*/
|
|
23
|
+
export function TypeAliasDeclaration(props: TypedAliasDeclarationProps) {
|
|
24
|
+
const { $ } = useTsp();
|
|
25
|
+
|
|
26
|
+
const originalName =
|
|
27
|
+
props.name ??
|
|
28
|
+
("name" in props.type && typeof props.type.name === "string" ? props.type.name : "");
|
|
29
|
+
|
|
30
|
+
if (!originalName || originalName === "") {
|
|
31
|
+
reportDiagnostic($.program, { code: "type-declaration-missing-name", target: props.type });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const doc = props.doc ?? $.type.getDoc(props.type);
|
|
35
|
+
const refkeys = declarationRefkeys(props.refkey, props.type);
|
|
36
|
+
|
|
37
|
+
// For Model template instances (e.g., alias StringResponse = Response<string>),
|
|
38
|
+
// emit as a dataclass since Python doesn't support parameterized type aliases.
|
|
39
|
+
// TypeSpec templates are macros that expand to concrete types.
|
|
40
|
+
if ($.model.is(props.type) && isTemplateInstance(props.type)) {
|
|
41
|
+
const namePolicy = py.usePythonNamePolicy();
|
|
42
|
+
const plausibleName = $.type.getPlausibleName(props.type as Model);
|
|
43
|
+
const name = props.name ?? namePolicy.getName(plausibleName, "class");
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<ClassDeclaration doc={doc} type={props.type} name={name} refkey={refkeys}>
|
|
47
|
+
{props.children}
|
|
48
|
+
</ClassDeclaration>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// For other types (scalars, unions, operations), emit as a type alias
|
|
53
|
+
const name = py.usePythonNamePolicy().getName(originalName, "variable");
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<py.VariableDeclaration
|
|
57
|
+
doc={doc}
|
|
58
|
+
name={name}
|
|
59
|
+
refkey={refkeys}
|
|
60
|
+
omitNone={true}
|
|
61
|
+
type={typingModule["."]["TypeAlias"]}
|
|
62
|
+
initializer={<TypeExpression type={props.type} noReference />}
|
|
63
|
+
>
|
|
64
|
+
{props.children}
|
|
65
|
+
</py.VariableDeclaration>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./type-declaration.js";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { d } from "@alloy-js/core/testing";
|
|
3
|
+
import { t } from "@typespec/compiler/testing";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { getOutput } from "../../test-utils.js";
|
|
6
|
+
import { TypeDeclaration } from "./type-declaration.js";
|
|
7
|
+
|
|
8
|
+
describe("Python TypeDeclaration dispatcher", () => {
|
|
9
|
+
it("dispatches to EnumDeclaration for enums", async () => {
|
|
10
|
+
const { program, Foo } = await Tester.compile(t.code`
|
|
11
|
+
enum ${t.enum("Foo")} {
|
|
12
|
+
one: 1,
|
|
13
|
+
two: 2,
|
|
14
|
+
three: 3
|
|
15
|
+
}
|
|
16
|
+
`);
|
|
17
|
+
|
|
18
|
+
const output = getOutput(program, [<TypeDeclaration type={Foo} />]);
|
|
19
|
+
expect(output).toRenderTo(d`
|
|
20
|
+
from enum import IntEnum
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Foo(IntEnum):
|
|
24
|
+
ONE = 1
|
|
25
|
+
TWO = 2
|
|
26
|
+
THREE = 3
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
`);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("dispatches scalars to TypeAliasDeclaration", async () => {
|
|
33
|
+
const { program, MyDate } = await Tester.compile(t.code`
|
|
34
|
+
scalar ${t.scalar("MyDate")} extends utcDateTime;
|
|
35
|
+
`);
|
|
36
|
+
|
|
37
|
+
const output = getOutput(program, [<TypeDeclaration type={MyDate} />]);
|
|
38
|
+
expect(output).toRenderTo(d`
|
|
39
|
+
from datetime import datetime
|
|
40
|
+
from typing import TypeAlias
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
my_date: TypeAlias = datetime`);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("dispatches arrays (model is Array<T>) to type alias with list[T]", async () => {
|
|
47
|
+
const { program, Items } = await Tester.compile(t.code`
|
|
48
|
+
model ${t.model("Items")} is Array<int32>;
|
|
49
|
+
`);
|
|
50
|
+
|
|
51
|
+
const output = getOutput(program, [<TypeDeclaration type={Items} />]);
|
|
52
|
+
expect(output).toRenderTo(d`
|
|
53
|
+
from typing import TypeAlias
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
items: TypeAlias = list[int]`);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useTsp } from "#core/context/index.js";
|
|
2
|
+
import * as py from "@alloy-js/python";
|
|
3
|
+
import type { Type } from "@typespec/compiler";
|
|
4
|
+
import { EnumDeclaration } from "../enum-declaration/enum-declaration.js";
|
|
5
|
+
import { TypeAliasDeclaration } from "../type-alias-declaration/type-alias-declaration.js";
|
|
6
|
+
|
|
7
|
+
export interface TypeDeclarationProps extends Omit<py.BaseDeclarationProps, "name"> {
|
|
8
|
+
name?: string;
|
|
9
|
+
type: Type;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Single entry point to declare a Python symbol for any TypeSpec `Type`.
|
|
14
|
+
*/
|
|
15
|
+
export function TypeDeclaration(props: TypeDeclarationProps) {
|
|
16
|
+
const { $ } = useTsp();
|
|
17
|
+
const { type, ...restProps } = props;
|
|
18
|
+
const doc = props.doc ?? $.type.getDoc(type);
|
|
19
|
+
switch (type.kind) {
|
|
20
|
+
case "Enum":
|
|
21
|
+
return <EnumDeclaration doc={doc} type={type} {...restProps} />;
|
|
22
|
+
default:
|
|
23
|
+
// All other kinds map to a Python type alias using TypeExpression
|
|
24
|
+
return <TypeAliasDeclaration doc={doc} type={type} {...restProps} />;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./type-expression.js";
|