forked from microsoft/typespec
-
Notifications
You must be signed in to change notification settings - Fork 1
Add typing #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add typing #38
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
2fe0775
Add Atom
mauriciogardini e54cd4c
Add typing
mauriciogardini ec976e5
Fix
mauriciogardini a22e3c9
Fix
mauriciogardini f0730a8
Add typing
mauriciogardini f83ebcc
Fix
mauriciogardini 9a91a42
Merge branch 'feature/typing' of https://github.com/pinterest/typespe…
mauriciogardini 20fa45b
Merge branch 'feature/ef-python' of https://github.com/pinterest/type…
mauriciogardini 292d2ee
Fix comment
mauriciogardini c2e8fda
Add TODOs
mauriciogardini File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import type { SymbolCreator } from "@alloy-js/core"; | ||
| import { createModule } from "@alloy-js/python"; | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| type dummy = SymbolCreator; | ||
|
|
||
| export const datetimeModule = createModule({ | ||
| name: "datetime", | ||
| descriptor: { | ||
| ".": ["datetime", "date", "time", "timedelta", "timezone"], | ||
| }, | ||
| }); | ||
|
|
||
| export const decimalModule = createModule({ | ||
| name: "decimal", | ||
| descriptor: { | ||
| ".": ["Decimal"], | ||
| }, | ||
| }); | ||
|
|
||
| export const typingModule = createModule({ | ||
| name: "typing", | ||
| descriptor: { | ||
| ".": ["Any", "NoReturn", "Tuple"], | ||
| }, | ||
| }); |
41 changes: 41 additions & 0 deletions
41
packages/emitter-framework/src/python/components/array-expression/array-expression.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { render, type Children } from "@alloy-js/core"; | ||
| import { d } from "@alloy-js/core/testing"; | ||
| import { SourceFile } from "@alloy-js/python"; | ||
| import type { BasicTestRunner } from "@typespec/compiler/testing"; | ||
| import { beforeEach, describe, it } from "vitest"; | ||
| import { Output } from "../../../../src/core/components/output.jsx"; | ||
| import { createEmitterFrameworkTestRunner } from "../../test-host.js"; | ||
| import { assertFileContents, compileModelPropertyType, getExternals } from "../../test-utils.js"; | ||
| import { TypeExpression } from "../type-expression/type-expression.jsx"; | ||
|
|
||
| let runner: BasicTestRunner; | ||
|
|
||
| beforeEach(async () => { | ||
| runner = await createEmitterFrameworkTestRunner(); | ||
| }); | ||
|
|
||
| function Wrapper(props: { children: Children }) { | ||
| return ( | ||
| <Output program={runner.program} externals={getExternals()}> | ||
| <SourceFile path="test.py">{props.children}</SourceFile> | ||
| </Output> | ||
| ); | ||
| } | ||
|
|
||
| describe("map array expression to Python list", () => { | ||
| it.each([["string[]", "list[str]"]])("%s => %s", async (tspType, pythonType) => { | ||
| const type = await compileModelPropertyType(tspType, runner); | ||
| const res = render( | ||
| <Wrapper> | ||
| <TypeExpression type={type} /> | ||
| </Wrapper>, | ||
| ); | ||
|
|
||
| assertFileContents( | ||
| res, | ||
| d` | ||
| ${pythonType} | ||
| `, | ||
| ); | ||
| }); | ||
| }); |
11 changes: 11 additions & 0 deletions
11
packages/emitter-framework/src/python/components/array-expression/array-expression.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { code } from "@alloy-js/core"; | ||
| import type { Type } from "@typespec/compiler"; | ||
| import { TypeExpression } from "../type-expression/type-expression.js"; | ||
|
|
||
| export interface ArrayExpressionProps { | ||
| elementType: Type; | ||
| } | ||
|
|
||
| export function ArrayExpression({ elementType }: ArrayExpressionProps) { | ||
| return code`list[${(<TypeExpression type={elementType} />)}]`; | ||
| } |
41 changes: 41 additions & 0 deletions
41
...ages/emitter-framework/src/python/components/record-expression/record-expression.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { render, type Children } from "@alloy-js/core"; | ||
| import { d } from "@alloy-js/core/testing"; | ||
| import { SourceFile } from "@alloy-js/python"; | ||
| import type { BasicTestRunner } from "@typespec/compiler/testing"; | ||
| import { beforeEach, describe, it } from "vitest"; | ||
| import { Output } from "../../../../src/core/components/output.jsx"; | ||
| import { createEmitterFrameworkTestRunner } from "../../test-host.js"; | ||
| import { assertFileContents, compileModelPropertyType, getExternals } from "../../test-utils.js"; | ||
| import { TypeExpression } from "../type-expression/type-expression.jsx"; | ||
|
|
||
| let runner: BasicTestRunner; | ||
|
|
||
| beforeEach(async () => { | ||
| runner = await createEmitterFrameworkTestRunner(); | ||
| }); | ||
|
|
||
| function Wrapper(props: { children: Children }) { | ||
| return ( | ||
| <Output program={runner.program} externals={getExternals()}> | ||
| <SourceFile path="test.py">{props.children}</SourceFile> | ||
| </Output> | ||
| ); | ||
| } | ||
|
|
||
| describe("map Record to Python dict", () => { | ||
| it.each([["Record<boolean>", "dict[str, bool]"]])("%s => %s", async (tspType, pythonType) => { | ||
| const type = await compileModelPropertyType(tspType, runner); | ||
| const res = render( | ||
| <Wrapper> | ||
| <TypeExpression type={type} /> | ||
| </Wrapper>, | ||
| ); | ||
|
|
||
| assertFileContents( | ||
| res, | ||
| d` | ||
| ${pythonType} | ||
| `, | ||
| ); | ||
| }); | ||
| }); |
13 changes: 13 additions & 0 deletions
13
packages/emitter-framework/src/python/components/record-expression/record-expression.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import { code } from "@alloy-js/core"; | ||
| import type { Type } from "@typespec/compiler"; | ||
| import { TypeExpression } from "../type-expression/type-expression.js"; | ||
|
|
||
| export interface RecordExpressionProps { | ||
| elementType: Type; | ||
| } | ||
|
|
||
| export function RecordExpression({ elementType }: RecordExpressionProps) { | ||
| return code` | ||
| dict[str, ${(<TypeExpression type={elementType} />)}] | ||
| `; | ||
| } |
150 changes: 150 additions & 0 deletions
150
...er-framework/src/python/components/type-alias-declaration/type-alias-declaration.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,150 @@ | ||
| import { SourceFile } from "@alloy-js/python"; | ||
| import type { Namespace } from "@typespec/compiler"; | ||
| import { describe, expect, it } from "vitest"; | ||
| import { Output } from "../../../../src/core/components/output.jsx"; | ||
| import { getProgram } from "../../test-host.js"; | ||
| import { getExternals } from "../../test-utils.js"; | ||
| import { TypeAliasDeclaration } from "./type-alias-declaration.jsx"; | ||
|
|
||
| describe("Python Declaration equivalency to Type Alias", () => { | ||
| describe("Type Alias Declaration bound to Typespec Scalar", () => { | ||
| describe("Scalar extends utcDateTime", () => { | ||
| it("creates a type alias declaration for a utcDateTime without encoding", async () => { | ||
| const program = await getProgram(` | ||
| namespace DemoService; | ||
| scalar MyDate extends utcDateTime; | ||
| `); | ||
|
|
||
| const [namespace] = program.resolveTypeReference("DemoService"); | ||
| const scalar = Array.from((namespace as Namespace).scalars.values())[0]; | ||
|
|
||
| expect( | ||
| <Output program={program} externals={getExternals()}> | ||
| <SourceFile path="test.py"> | ||
| <TypeAliasDeclaration type={scalar} /> | ||
| </SourceFile> | ||
| </Output>, | ||
| ).toRenderTo(` | ||
| from datetime import datetime | ||
|
|
||
| MyDate: datetime`); | ||
| }); | ||
|
|
||
| it("creates a type alias declaration with JSDoc", async () => { | ||
| const program = await getProgram(` | ||
| namespace DemoService; | ||
| /** | ||
| * Type to represent a date | ||
| */ | ||
| scalar MyDate extends utcDateTime; | ||
| `); | ||
|
|
||
| const [namespace] = program.resolveTypeReference("DemoService"); | ||
| const scalar = Array.from((namespace as Namespace).scalars.values())[0]; | ||
|
|
||
| expect( | ||
| <Output program={program} externals={getExternals()}> | ||
| <SourceFile path="test.py"> | ||
| <TypeAliasDeclaration type={scalar} /> | ||
| </SourceFile> | ||
| </Output>, | ||
| ).toRenderTo(` | ||
| from datetime import datetime | ||
|
|
||
| # Type to represent a date | ||
| MyDate: datetime`); | ||
| }); | ||
|
|
||
| it("can override JSDoc", async () => { | ||
| const program = await getProgram(` | ||
| namespace DemoService; | ||
| /** | ||
| * Type to represent a date | ||
| */ | ||
| scalar MyDate extends utcDateTime; | ||
| `); | ||
|
|
||
| const [namespace] = program.resolveTypeReference("DemoService"); | ||
| const scalar = Array.from((namespace as Namespace).scalars.values())[0]; | ||
|
|
||
| expect( | ||
| <Output program={program} externals={getExternals()}> | ||
| <SourceFile path="test.py"> | ||
| <TypeAliasDeclaration doc={"Overridden Doc"} type={scalar} /> | ||
| </SourceFile> | ||
| </Output>, | ||
| ).toRenderTo(` | ||
| from datetime import datetime | ||
|
|
||
| # Overridden Doc | ||
| MyDate: datetime`); | ||
| }); | ||
|
|
||
| it("creates a type alias declaration for a utcDateTime with unixTimeStamp encoding", async () => { | ||
| const program = await getProgram(` | ||
| namespace DemoService; | ||
| @encode("unixTimestamp", int32) | ||
| scalar MyDate extends utcDateTime; | ||
| `); | ||
|
|
||
| const [namespace] = program.resolveTypeReference("DemoService"); | ||
| const scalar = Array.from((namespace as Namespace).scalars.values())[0]; | ||
|
|
||
| expect( | ||
| <Output program={program} externals={getExternals()}> | ||
| <SourceFile path="test.py"> | ||
| <TypeAliasDeclaration type={scalar} /> | ||
| </SourceFile> | ||
| </Output>, | ||
| ).toRenderTo(` | ||
| from datetime import datetime | ||
|
|
||
| MyDate: datetime`); | ||
| }); | ||
|
|
||
| it("creates a type alias declaration for a utcDateTime with rfc7231 encoding", async () => { | ||
| const program = await getProgram(` | ||
| namespace DemoService; | ||
| @encode("rfc7231") | ||
| scalar MyDate extends utcDateTime; | ||
| `); | ||
|
|
||
| const [namespace] = program.resolveTypeReference("DemoService"); | ||
| const scalar = Array.from((namespace as Namespace).scalars.values())[0]; | ||
|
|
||
| expect( | ||
| <Output program={program} externals={getExternals()}> | ||
| <SourceFile path="test.py"> | ||
| <TypeAliasDeclaration type={scalar} /> | ||
| </SourceFile> | ||
| </Output>, | ||
| ).toRenderTo(` | ||
| from datetime import datetime | ||
|
|
||
| MyDate: datetime`); | ||
| }); | ||
|
|
||
| it("creates a type alias declaration for a utcDateTime with rfc3339 encoding", async () => { | ||
| const program = await getProgram(` | ||
| namespace DemoService; | ||
| @encode("rfc3339") | ||
| scalar MyDate extends utcDateTime; | ||
| `); | ||
|
|
||
| const [namespace] = program.resolveTypeReference("DemoService"); | ||
| const scalar = Array.from((namespace as Namespace).scalars.values())[0]; | ||
|
|
||
| expect( | ||
| <Output program={program} externals={getExternals()}> | ||
| <SourceFile path="test.py"> | ||
| <TypeAliasDeclaration type={scalar} /> | ||
| </SourceFile> | ||
| </Output>, | ||
| ).toRenderTo(` | ||
| from datetime import datetime | ||
|
|
||
| MyDate: datetime`); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
55 changes: 55 additions & 0 deletions
55
...emitter-framework/src/python/components/type-alias-declaration/type-alias-declaration.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import * as py from "@alloy-js/python"; | ||
| import type { Type } from "@typespec/compiler"; | ||
| import { useTsp } from "../../../core/context/tsp-context.js"; | ||
| import { reportDiagnostic } from "../../../lib.js"; | ||
| import { declarationRefkeys } from "../../utils/refkey.js"; | ||
| import { TypeExpression } from "../type-expression/type-expression.jsx"; | ||
|
|
||
| export interface TypedAliasDeclarationProps extends Omit<py.BaseDeclarationProps, "name"> { | ||
| type: Type; | ||
| name?: string; | ||
| } | ||
|
|
||
| /** | ||
| * Create a Python type alias declaration. Pass the `type` prop to emit the | ||
| * type alias as the provided TypeSpec type. | ||
| */ | ||
| export function TypeAliasDeclaration(props: TypedAliasDeclarationProps) { | ||
| const { $ } = useTsp(); | ||
|
|
||
| const originalName = | ||
| props.name ?? | ||
| ("name" in props.type && typeof props.type.name === "string" ? props.type.name : ""); | ||
|
|
||
| if (!originalName || originalName === "") { | ||
| reportDiagnostic($.program, { code: "type-declaration-missing-name", target: props.type }); | ||
| } | ||
|
|
||
| const doc = props.doc ?? $.type.getDoc(props.type); | ||
| const refkeys = declarationRefkeys(props.refkey, props.type); | ||
|
|
||
| const name = py.usePythonNamePolicy().getName(originalName, "variable"); | ||
| // TODO: See how we will handle this kind of scenario: | ||
| // type Foo { | ||
| // bar(id: String): BarResponse | ||
| // | ||
| // Bar = Callable[[string], BarResponse] | ||
| // class Foo: | ||
| // bar: Bar | ||
| // | ||
| // Maybe this won't done by this emitter, but we might want that eventually to be done by some emitter. | ||
| // | ||
| return ( | ||
| // TODO: See if there's a need to make py.VariableDeclaration consider props.children | ||
| // (it doesn't at this moment, and there isn't a scenario where we need it) | ||
| <py.VariableDeclaration | ||
| doc={doc} | ||
| name={name} | ||
| refkey={refkeys} | ||
| omitNone={true} | ||
| type={<TypeExpression type={props.type} noReference />} | ||
mauriciogardini marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| > | ||
| {props.children} | ||
| </py.VariableDeclaration> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.