@typespec/emitter-framework 0.15.0-dev.3 → 0.15.0
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 +14 -16
- 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/package.json +12 -5
- package/package.json.bak +14 -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
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as py from "@alloy-js/python";
|
|
2
|
+
import { type Interface, type Model } from "@typespec/compiler";
|
|
3
|
+
import { useTsp } from "../../../core/context/tsp-context.js";
|
|
4
|
+
import { reportDiagnostic } from "../../../lib.js";
|
|
5
|
+
import { declarationRefkeys } from "../../utils/refkey.js";
|
|
6
|
+
import { DocElement } from "../doc-element/doc-element.js";
|
|
7
|
+
import { ClassBases } from "./class-bases.js";
|
|
8
|
+
import { ClassBody } from "./class-body.js";
|
|
9
|
+
import { MethodProvider } from "./class-method.js";
|
|
10
|
+
|
|
11
|
+
export interface ClassDeclarationPropsWithType extends Omit<py.ClassDeclarationProps, "name"> {
|
|
12
|
+
type: Model | Interface;
|
|
13
|
+
name?: string;
|
|
14
|
+
abstract?: boolean; // Global override for the abstract flag
|
|
15
|
+
methodType?: "method" | "class" | "static"; // Global override for the method type
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ClassDeclarationProps = ClassDeclarationPropsWithType | py.ClassDeclarationProps;
|
|
19
|
+
|
|
20
|
+
function isTypedClassDeclarationProps(
|
|
21
|
+
props: ClassDeclarationProps,
|
|
22
|
+
): props is ClassDeclarationPropsWithType {
|
|
23
|
+
return "type" in props;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Converts TypeSpec Models and Interfaces to Python classes.
|
|
28
|
+
*
|
|
29
|
+
* - **Models** are converted into Dataclasses with `@dataclass(kw_only=True)` + fields
|
|
30
|
+
* - **Interfaces** are converted into Abstract classes (ABC) with abstract methods
|
|
31
|
+
* - For models that extends another model, we convert that into Python class inheritance
|
|
32
|
+
* - For interfaces that extends another interface, there's no inheritance, since
|
|
33
|
+
* TypeSpec flattens the inheritance
|
|
34
|
+
*
|
|
35
|
+
* @param props - The props for the class declaration.
|
|
36
|
+
* @returns The class declaration.
|
|
37
|
+
*/
|
|
38
|
+
export function ClassDeclaration(props: ClassDeclarationProps) {
|
|
39
|
+
const { $ } = useTsp();
|
|
40
|
+
|
|
41
|
+
// Interfaces are rendered as abstract classes (ABC) with abstract methods
|
|
42
|
+
// Models are rendered as concrete dataclasses with fields
|
|
43
|
+
// If we are explicitly overriding the class as abstract or the type is not a model, we need to create an abstract class
|
|
44
|
+
const abstract =
|
|
45
|
+
("abstract" in props && props.abstract) || ("type" in props && !$.model.is(props.type));
|
|
46
|
+
|
|
47
|
+
const type = "type" in props ? props.type : undefined;
|
|
48
|
+
const docSource = props.doc ?? (type ? $.type.getDoc(type) : undefined);
|
|
49
|
+
const docElement = docSource ? <DocElement doc={docSource} component={py.ClassDoc} /> : undefined;
|
|
50
|
+
|
|
51
|
+
// TODO: When TypeSpec adds true generics support, pass extraBases with Generic[T, ...] here.
|
|
52
|
+
// Currently, TypeSpec templates are macros that expand to concrete types, so we don't
|
|
53
|
+
// generate Python generics (TypeVar/Generic) for template declarations.
|
|
54
|
+
const basesType = ClassBases({
|
|
55
|
+
type: "type" in props ? props.type : undefined,
|
|
56
|
+
bases: props.bases,
|
|
57
|
+
abstract,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!isTypedClassDeclarationProps(props)) {
|
|
61
|
+
return (
|
|
62
|
+
<py.ClassDeclaration
|
|
63
|
+
{...props}
|
|
64
|
+
doc={docElement}
|
|
65
|
+
{...(basesType.length ? { bases: basesType } : {})}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const namePolicy = py.usePythonNamePolicy();
|
|
71
|
+
|
|
72
|
+
let name = props.name ?? props.type.name;
|
|
73
|
+
if (!name) {
|
|
74
|
+
reportDiagnostic($.program, { code: "type-declaration-missing-name", target: props.type });
|
|
75
|
+
}
|
|
76
|
+
name = namePolicy.getName(name, "class");
|
|
77
|
+
|
|
78
|
+
const refkeys = declarationRefkeys(props.refkey, props.type);
|
|
79
|
+
|
|
80
|
+
// Check for models with additional properties (Record-based scenarios)
|
|
81
|
+
// This check must happen here (in addition to ClassBody) because models with no properties
|
|
82
|
+
// (e.g., `model Foo is Record<string>`) won't render a ClassBody, so the error would never be thrown
|
|
83
|
+
if ($.model.is(props.type)) {
|
|
84
|
+
const additionalPropsRecord = $.model.getAdditionalPropertiesRecord(props.type);
|
|
85
|
+
if (additionalPropsRecord) {
|
|
86
|
+
throw new Error("Models with additional properties (Record[…]) are not supported");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Array-based models (e.g., model Foo is Array<T>) use regular classes, not dataclasses,
|
|
91
|
+
// since Array models in TypeSpec can't have properties, so they behave more like a class
|
|
92
|
+
// that inherits from a list.
|
|
93
|
+
// Similarly, interfaces should use regular classes (ABC) not dataclasses, since interfaces
|
|
94
|
+
// only define abstract methods, not fields.
|
|
95
|
+
const isArrayModel = $.model.is(props.type) && $.array.is(props.type);
|
|
96
|
+
const isInterface = props.type.kind === "Interface";
|
|
97
|
+
const useDataclass = !isArrayModel && !isInterface;
|
|
98
|
+
|
|
99
|
+
const ClassComponent = useDataclass ? py.DataclassDeclaration : py.ClassDeclaration;
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<MethodProvider value={props.methodType}>
|
|
103
|
+
<ClassComponent
|
|
104
|
+
doc={docElement}
|
|
105
|
+
name={name}
|
|
106
|
+
{...(basesType.length ? { bases: basesType } : {})}
|
|
107
|
+
refkey={refkeys}
|
|
108
|
+
kwOnly={useDataclass ? true : undefined}
|
|
109
|
+
>
|
|
110
|
+
<ClassBody type={props.type} abstract={abstract} methodType={props.methodType}>
|
|
111
|
+
{props.children}
|
|
112
|
+
</ClassBody>
|
|
113
|
+
</ClassComponent>
|
|
114
|
+
</MethodProvider>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { t } from "@typespec/compiler/testing";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { ClassDeclaration } from "../../../../src/python/components/class-declaration/class-declaration.js";
|
|
5
|
+
import { getOutput } from "../../test-utils.js";
|
|
6
|
+
|
|
7
|
+
describe("Python Class Members", () => {
|
|
8
|
+
describe("default values", () => {
|
|
9
|
+
it("renders string default values", async () => {
|
|
10
|
+
const { program, MyModel } = await Tester.compile(t.code`
|
|
11
|
+
model ${t.model("MyModel")} {
|
|
12
|
+
name: string = "default";
|
|
13
|
+
description?: string = "optional with default";
|
|
14
|
+
emptyString: string = "";
|
|
15
|
+
}
|
|
16
|
+
`);
|
|
17
|
+
|
|
18
|
+
expect(getOutput(program, [<ClassDeclaration type={MyModel} />])).toRenderTo(
|
|
19
|
+
`
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(kw_only=True)
|
|
25
|
+
class MyModel:
|
|
26
|
+
name: str = "default"
|
|
27
|
+
description: Optional[str] = "optional with default"
|
|
28
|
+
empty_string: str = ""
|
|
29
|
+
|
|
30
|
+
`,
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("renders boolean default values", async () => {
|
|
35
|
+
const { program, BooleanModel } = await Tester.compile(t.code`
|
|
36
|
+
model ${t.model("BooleanModel")} {
|
|
37
|
+
isActive: boolean = true;
|
|
38
|
+
isDeleted: boolean = false;
|
|
39
|
+
optional?: boolean = true;
|
|
40
|
+
}
|
|
41
|
+
`);
|
|
42
|
+
|
|
43
|
+
expect(getOutput(program, [<ClassDeclaration type={BooleanModel} />])).toRenderTo(
|
|
44
|
+
`
|
|
45
|
+
from dataclasses import dataclass
|
|
46
|
+
from typing import Optional
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(kw_only=True)
|
|
50
|
+
class BooleanModel:
|
|
51
|
+
is_active: bool = True
|
|
52
|
+
is_deleted: bool = False
|
|
53
|
+
optional: Optional[bool] = True
|
|
54
|
+
|
|
55
|
+
`,
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("renders array default values", async () => {
|
|
60
|
+
const { program, ArrayModel } = await Tester.compile(t.code`
|
|
61
|
+
model ${t.model("ArrayModel")} {
|
|
62
|
+
tags: string[] = #["tag1", "tag2"];
|
|
63
|
+
emptyArray: int32[] = #[];
|
|
64
|
+
numbers: int32[] = #[1, 2, 3];
|
|
65
|
+
}
|
|
66
|
+
`);
|
|
67
|
+
|
|
68
|
+
expect(getOutput(program, [<ClassDeclaration type={ArrayModel} />])).toRenderTo(
|
|
69
|
+
`
|
|
70
|
+
from dataclasses import dataclass
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(kw_only=True)
|
|
74
|
+
class ArrayModel:
|
|
75
|
+
tags: list[str] = ["tag1", "tag2"]
|
|
76
|
+
empty_array: list[int] = []
|
|
77
|
+
numbers: list[int] = [1, 2, 3]
|
|
78
|
+
|
|
79
|
+
`,
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("renders integer default values without .0 suffix", async () => {
|
|
84
|
+
const { program, IntegerModel } = await Tester.compile(t.code`
|
|
85
|
+
model ${t.model("IntegerModel")} {
|
|
86
|
+
count: int32 = 42;
|
|
87
|
+
bigNumber: int64 = 1000000;
|
|
88
|
+
smallNumber: int8 = 127;
|
|
89
|
+
unsignedValue: uint32 = 100;
|
|
90
|
+
safeIntValue: safeint = 999;
|
|
91
|
+
}
|
|
92
|
+
`);
|
|
93
|
+
|
|
94
|
+
expect(getOutput(program, [<ClassDeclaration type={IntegerModel} />])).toRenderTo(
|
|
95
|
+
`
|
|
96
|
+
from dataclasses import dataclass
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(kw_only=True)
|
|
100
|
+
class IntegerModel:
|
|
101
|
+
count: int = 42
|
|
102
|
+
big_number: int = 1000000
|
|
103
|
+
small_number: int = 127
|
|
104
|
+
unsigned_value: int = 100
|
|
105
|
+
safe_int_value: int = 999
|
|
106
|
+
|
|
107
|
+
`,
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("renders float and decimal default values correctly", async () => {
|
|
112
|
+
const { program, NumericDefaults } = await Tester.compile(t.code`
|
|
113
|
+
|
|
114
|
+
scalar customFloat extends float;
|
|
115
|
+
scalar customDecimal extends decimal;
|
|
116
|
+
|
|
117
|
+
model ${t.model("NumericDefaults")} {
|
|
118
|
+
// Float variants with decimal values
|
|
119
|
+
floatBase: float = 1.5;
|
|
120
|
+
float32Value: float32 = 2.5;
|
|
121
|
+
float64Value: float64 = 3.5;
|
|
122
|
+
customFloatValue: customFloat = 4.5;
|
|
123
|
+
|
|
124
|
+
// Float variants with integer values (should render with .0)
|
|
125
|
+
floatInt: float = 10;
|
|
126
|
+
float32Int: float32 = 20;
|
|
127
|
+
float64Int: float64 = 30;
|
|
128
|
+
|
|
129
|
+
// Decimal variants
|
|
130
|
+
decimalBase: decimal = 100.25;
|
|
131
|
+
decimal128Value: decimal128 = 200.75;
|
|
132
|
+
customDecimalValue: customDecimal = 300.125;
|
|
133
|
+
|
|
134
|
+
// Decimal with integer values (should render with .0)
|
|
135
|
+
decimalInt: decimal = 400;
|
|
136
|
+
decimal128Int: decimal128 = 500;
|
|
137
|
+
}
|
|
138
|
+
`);
|
|
139
|
+
|
|
140
|
+
expect(getOutput(program, [<ClassDeclaration type={NumericDefaults} />])).toRenderTo(
|
|
141
|
+
`
|
|
142
|
+
from dataclasses import dataclass
|
|
143
|
+
from decimal import Decimal
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@dataclass(kw_only=True)
|
|
147
|
+
class NumericDefaults:
|
|
148
|
+
float_base: float = 1.5
|
|
149
|
+
float32_value: float = 2.5
|
|
150
|
+
float64_value: float = 3.5
|
|
151
|
+
custom_float_value: float = 4.5
|
|
152
|
+
float_int: float = 10.0
|
|
153
|
+
float32_int: float = 20.0
|
|
154
|
+
float64_int: float = 30.0
|
|
155
|
+
decimal_base: Decimal = 100.25
|
|
156
|
+
decimal128_value: Decimal = 200.75
|
|
157
|
+
custom_decimal_value: Decimal = 300.125
|
|
158
|
+
decimal_int: Decimal = 400.0
|
|
159
|
+
decimal128_int: Decimal = 500.0
|
|
160
|
+
|
|
161
|
+
`,
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("distinguishes between integer and float types with same numeric value", async () => {
|
|
166
|
+
const { program, MixedNumeric } = await Tester.compile(t.code`
|
|
167
|
+
model ${t.model("MixedNumeric")} {
|
|
168
|
+
intValue: int32 = 100;
|
|
169
|
+
int64Value: int64 = 100;
|
|
170
|
+
floatValue: float = 100;
|
|
171
|
+
float64Value: float64 = 100;
|
|
172
|
+
decimalValue: decimal = 100;
|
|
173
|
+
}
|
|
174
|
+
`);
|
|
175
|
+
|
|
176
|
+
expect(getOutput(program, [<ClassDeclaration type={MixedNumeric} />])).toRenderTo(
|
|
177
|
+
`
|
|
178
|
+
from dataclasses import dataclass
|
|
179
|
+
from decimal import Decimal
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@dataclass(kw_only=True)
|
|
183
|
+
class MixedNumeric:
|
|
184
|
+
int_value: int = 100
|
|
185
|
+
int64_value: int = 100
|
|
186
|
+
float_value: float = 100.0
|
|
187
|
+
float64_value: float = 100.0
|
|
188
|
+
decimal_value: Decimal = 100.0
|
|
189
|
+
|
|
190
|
+
`,
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { typingModule } from "#python/builtins.js";
|
|
2
|
+
import { type Children } from "@alloy-js/core";
|
|
3
|
+
import * as py from "@alloy-js/python";
|
|
4
|
+
import { type ModelProperty, type Operation } from "@typespec/compiler";
|
|
5
|
+
import { useTsp } from "../../../core/context/tsp-context.js";
|
|
6
|
+
import { TypeExpression } from "../type-expression/type-expression.js";
|
|
7
|
+
import { Method } from "./class-method.js";
|
|
8
|
+
import { PrimitiveInitializer } from "./primitive-initializer.js";
|
|
9
|
+
|
|
10
|
+
export interface ClassMemberProps {
|
|
11
|
+
type: ModelProperty | Operation;
|
|
12
|
+
doc?: Children;
|
|
13
|
+
optional?: boolean;
|
|
14
|
+
methodType?: "method" | "class" | "static";
|
|
15
|
+
abstract?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates the class member for the property.
|
|
20
|
+
* @param props - The props for the class member.
|
|
21
|
+
* @returns The class member.
|
|
22
|
+
*/
|
|
23
|
+
export function ClassMember(props: ClassMemberProps) {
|
|
24
|
+
const { $ } = useTsp();
|
|
25
|
+
const namer = py.usePythonNamePolicy();
|
|
26
|
+
const name = namer.getName(props.type.name, "class-member");
|
|
27
|
+
const doc = props.doc ?? $.type.getDoc(props.type);
|
|
28
|
+
|
|
29
|
+
if ($.modelProperty.is(props.type)) {
|
|
30
|
+
// Map never-typed properties to typing.Never
|
|
31
|
+
|
|
32
|
+
const unpackedType = props.type.type;
|
|
33
|
+
const isOptional = props.optional ?? props.type.optional ?? false;
|
|
34
|
+
const defaultValue = props.type.defaultValue;
|
|
35
|
+
const initializer = defaultValue ? (
|
|
36
|
+
<PrimitiveInitializer defaultValue={defaultValue} propertyType={unpackedType} />
|
|
37
|
+
) : undefined;
|
|
38
|
+
const unpackedTypeNode: Children = <TypeExpression type={unpackedType} />;
|
|
39
|
+
const typeNode = isOptional ? (
|
|
40
|
+
<py.TypeReference
|
|
41
|
+
refkey={typingModule["."].Optional}
|
|
42
|
+
typeArgs={[unpackedTypeNode]}
|
|
43
|
+
></py.TypeReference>
|
|
44
|
+
) : (
|
|
45
|
+
unpackedTypeNode
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const classMemberProps = {
|
|
49
|
+
doc,
|
|
50
|
+
name,
|
|
51
|
+
optional: isOptional,
|
|
52
|
+
...(typeNode ? { type: typeNode } : {}),
|
|
53
|
+
...(initializer ? { initializer } : {}),
|
|
54
|
+
omitNone: !isOptional,
|
|
55
|
+
};
|
|
56
|
+
return <py.VariableDeclaration {...classMemberProps} />;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if ($.operation.is(props.type)) {
|
|
60
|
+
return (
|
|
61
|
+
<Method type={props.type} doc={doc} methodType={props.methodType} abstract={props.abstract} />
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// If type is neither ModelProperty nor Operation, return empty fragment
|
|
66
|
+
return <></>;
|
|
67
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { getProgram } from "#test/utils.js";
|
|
3
|
+
import * as py from "@alloy-js/python";
|
|
4
|
+
import { t } from "@typespec/compiler/testing";
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { ClassDeclaration } from "../../../../src/python/components/class-declaration/class-declaration.js";
|
|
7
|
+
import { Method } from "../../../../src/python/components/class-declaration/class-method.js";
|
|
8
|
+
import { getOutput } from "../../test-utils.js";
|
|
9
|
+
|
|
10
|
+
describe("interface methods with a `type` prop", () => {
|
|
11
|
+
it("creates a class method from an interface method", async () => {
|
|
12
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
13
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
14
|
+
`);
|
|
15
|
+
|
|
16
|
+
expect(
|
|
17
|
+
getOutput(program, [
|
|
18
|
+
<ClassDeclaration name="basicInterface">
|
|
19
|
+
<Method async type={getName} />
|
|
20
|
+
</ClassDeclaration>,
|
|
21
|
+
]),
|
|
22
|
+
).toRenderTo(`
|
|
23
|
+
class BasicInterface:
|
|
24
|
+
async def get_name(self, id: str) -> str:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
`);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("creates a class method that is a classmethod", async () => {
|
|
32
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
33
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
34
|
+
`);
|
|
35
|
+
|
|
36
|
+
expect(
|
|
37
|
+
getOutput(program, [
|
|
38
|
+
<ClassDeclaration name="basicInterface">
|
|
39
|
+
<Method async type={getName} methodType="class" />
|
|
40
|
+
</ClassDeclaration>,
|
|
41
|
+
]),
|
|
42
|
+
).toRenderTo(`
|
|
43
|
+
class BasicInterface:
|
|
44
|
+
@classmethod
|
|
45
|
+
async def get_name(cls, id: str) -> str:
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
`);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("creates a class method that is a staticmethod", async () => {
|
|
53
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
54
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
55
|
+
`);
|
|
56
|
+
|
|
57
|
+
expect(
|
|
58
|
+
getOutput(program, [
|
|
59
|
+
<ClassDeclaration name="basicInterface">
|
|
60
|
+
<Method async type={getName} methodType="static" />
|
|
61
|
+
</ClassDeclaration>,
|
|
62
|
+
]),
|
|
63
|
+
).toRenderTo(`
|
|
64
|
+
class BasicInterface:
|
|
65
|
+
@staticmethod
|
|
66
|
+
async def get_name(id: str) -> str:
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
`);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("creates an async class method from an asyncinterface method", async () => {
|
|
74
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
75
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
76
|
+
`);
|
|
77
|
+
|
|
78
|
+
expect(
|
|
79
|
+
getOutput(program, [
|
|
80
|
+
<ClassDeclaration name="basicInterface">
|
|
81
|
+
<Method async type={getName} />
|
|
82
|
+
</ClassDeclaration>,
|
|
83
|
+
]),
|
|
84
|
+
).toRenderTo(`
|
|
85
|
+
class BasicInterface:
|
|
86
|
+
async def get_name(self, id: str) -> str:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
`);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("can append extra keyword-only parameters", async () => {
|
|
94
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
95
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
96
|
+
`);
|
|
97
|
+
|
|
98
|
+
expect(
|
|
99
|
+
getOutput(program, [
|
|
100
|
+
<ClassDeclaration name="basicInterface">
|
|
101
|
+
<Method type={getName} parameters={[{ name: "foo", type: "string" }]} />
|
|
102
|
+
</ClassDeclaration>,
|
|
103
|
+
]),
|
|
104
|
+
).toRenderTo(`
|
|
105
|
+
class BasicInterface:
|
|
106
|
+
def get_name(self, id: str, *, foo: str) -> str:
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("can add extra keyword-only parameters", async () => {
|
|
114
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
115
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
116
|
+
`);
|
|
117
|
+
|
|
118
|
+
expect(
|
|
119
|
+
getOutput(program, [
|
|
120
|
+
<ClassDeclaration name="basicInterface">
|
|
121
|
+
<Method type={getName} parameters={[{ name: "foo", type: "string" }]} />
|
|
122
|
+
</ClassDeclaration>,
|
|
123
|
+
]),
|
|
124
|
+
).toRenderTo(`
|
|
125
|
+
class BasicInterface:
|
|
126
|
+
def get_name(self, id: str, *, foo: str) -> str:
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
`);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("can replace parameters with raw params provided", async () => {
|
|
134
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
135
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
136
|
+
`);
|
|
137
|
+
|
|
138
|
+
expect(
|
|
139
|
+
getOutput(program, [
|
|
140
|
+
<ClassDeclaration name="basicInterface">
|
|
141
|
+
<Method
|
|
142
|
+
type={getName}
|
|
143
|
+
replaceParameters={true}
|
|
144
|
+
parameters={[
|
|
145
|
+
{ name: "foo", type: "string" },
|
|
146
|
+
{ name: "bar", type: "number" },
|
|
147
|
+
]}
|
|
148
|
+
/>
|
|
149
|
+
</ClassDeclaration>,
|
|
150
|
+
]),
|
|
151
|
+
).toRenderTo(`
|
|
152
|
+
class BasicInterface:
|
|
153
|
+
def get_name(self, *, foo: str, bar: float) -> str:
|
|
154
|
+
pass
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
`);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("can replace parameters with params having defaults (requires * marker)", async () => {
|
|
161
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
162
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
163
|
+
`);
|
|
164
|
+
|
|
165
|
+
expect(
|
|
166
|
+
getOutput(program, [
|
|
167
|
+
<ClassDeclaration name="basicInterface">
|
|
168
|
+
<Method
|
|
169
|
+
type={getName}
|
|
170
|
+
replaceParameters={true}
|
|
171
|
+
parameters={[
|
|
172
|
+
{ name: "foo", type: "string", default: <py.Atom jsValue={"default"} /> },
|
|
173
|
+
{ name: "bar", type: "number", default: <py.Atom jsValue={42} /> },
|
|
174
|
+
]}
|
|
175
|
+
/>
|
|
176
|
+
</ClassDeclaration>,
|
|
177
|
+
]),
|
|
178
|
+
).toRenderTo(`
|
|
179
|
+
class BasicInterface:
|
|
180
|
+
def get_name(self, *, foo: str = "default", bar: float = 42) -> str:
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
`);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("can override return type in a class method", async () => {
|
|
188
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
189
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
190
|
+
`);
|
|
191
|
+
|
|
192
|
+
expect(
|
|
193
|
+
getOutput(program, [
|
|
194
|
+
<ClassDeclaration name="basicInterface">
|
|
195
|
+
<Method type={getName} returnType="ASpecialString" />
|
|
196
|
+
</ClassDeclaration>,
|
|
197
|
+
]),
|
|
198
|
+
).toRenderTo(`
|
|
199
|
+
class BasicInterface:
|
|
200
|
+
def get_name(self, id: str) -> ASpecialString:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
`);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("can override method name in a class method", async () => {
|
|
208
|
+
const { program, getName } = await Tester.compile(t.code`
|
|
209
|
+
@test op ${t.op("getName")}(id: string): string;
|
|
210
|
+
`);
|
|
211
|
+
|
|
212
|
+
expect(
|
|
213
|
+
getOutput(program, [
|
|
214
|
+
<ClassDeclaration name="basicInterface">
|
|
215
|
+
<Method type={getName} name="get_name_custom" />
|
|
216
|
+
</ClassDeclaration>,
|
|
217
|
+
]),
|
|
218
|
+
).toRenderTo(`
|
|
219
|
+
class BasicInterface:
|
|
220
|
+
def get_name_custom(self, id: str) -> str:
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
`);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
describe("interface methods without a `type` prop", () => {
|
|
229
|
+
it("renders a plain interface method from a class method without a `type` prop", async () => {
|
|
230
|
+
const program = await getProgram("");
|
|
231
|
+
|
|
232
|
+
expect(
|
|
233
|
+
getOutput(program, [
|
|
234
|
+
<ClassDeclaration name="basicInterface">
|
|
235
|
+
<Method
|
|
236
|
+
name="plainMethod"
|
|
237
|
+
parameters={[{ name: "param1", type: "string" }]}
|
|
238
|
+
returnType="number"
|
|
239
|
+
/>
|
|
240
|
+
</ClassDeclaration>,
|
|
241
|
+
]),
|
|
242
|
+
).toRenderTo(`
|
|
243
|
+
class BasicInterface:
|
|
244
|
+
def plain_method(self, param1: string) -> number:
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
`);
|
|
249
|
+
});
|
|
250
|
+
});
|