From c148c97589b09d16c351b082535a6fc95b8fcd0c Mon Sep 17 00:00:00 2001 From: tadelesh Date: Thu, 15 Aug 2024 17:51:56 +0800 Subject: [PATCH 1/5] support query `explode` and path `allowReserved` --- packages/typespec-python/package.json | 4 ++-- packages/typespec-python/src/http.ts | 12 ++++++------ packages/typespec-python/src/utils.ts | 6 +++--- pnpm-lock.yaml | 22 +++++++++++----------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/typespec-python/package.json b/packages/typespec-python/package.json index d70afc2d2c..dc0c90e063 100644 --- a/packages/typespec-python/package.json +++ b/packages/typespec-python/package.json @@ -48,7 +48,7 @@ "@azure-tools/typespec-azure-core": ">=0.45.0 <1.0.0", "@azure-tools/typespec-azure-resource-manager": ">=0.45.0 <1.0.0", "@azure-tools/typespec-autorest": ">=0.45.0 <1.0.0", - "@azure-tools/typespec-client-generator-core": ">=0.45.1 <1.0.0", + "@azure-tools/typespec-client-generator-core": ">=0.45.3 <1.0.0", "@azure-tools/typespec-azure-rulesets": ">=0.45.0 <3.0.0", "@typespec/compiler": ">=0.59.1 <1.0.0", "@typespec/http": ">=0.59.0 <1.0.0", @@ -85,7 +85,7 @@ "rimraf": "~5.0.0", "typescript": "~5.1.3", "@azure-tools/typespec-azure-core": "~0.45.0", - "@azure-tools/typespec-client-generator-core": "0.45.1", + "@azure-tools/typespec-client-generator-core": "0.45.3", "@typespec/compiler": "~0.59.1", "@typespec/http": "~0.59.0", "@typespec/rest": "~0.59.0", diff --git a/packages/typespec-python/src/http.ts b/packages/typespec-python/src/http.ts index 220438b7d4..3fb6afdb9a 100644 --- a/packages/typespec-python/src/http.ts +++ b/packages/typespec-python/src/http.ts @@ -19,7 +19,7 @@ import { camelToSnakeCase, emitParamBase, getAddedOn, - getDelimeterAndExplode, + getDelimiterAndExplode, getDescriptionAndSummary, getImplementation, isAbstract, @@ -237,7 +237,7 @@ function emitHttpPathParameter(context: PythonSdkContext, para location: parameter.kind, implementation: getImplementation(context, parameter), clientDefaultValue: parameter.clientDefaultValue, - skipUrlEncoding: parameter.urlEncode === false, + skipUrlEncoding: parameter.allowReserved, }; } function emitHttpHeaderParameter( @@ -245,7 +245,7 @@ function emitHttpHeaderParameter( parameter: SdkHeaderParameter, ): Record { const base = emitParamBase(context, parameter); - const [delimiter, explode] = getDelimeterAndExplode(parameter); + const [delimiter, explode] = getDelimiterAndExplode(parameter); let clientDefaultValue = parameter.clientDefaultValue; if (isContentTypeParameter(parameter)) { // we switch to string type for content-type header @@ -270,7 +270,7 @@ function emitHttpQueryParameter( parameter: SdkQueryParameter, ): Record { const base = emitParamBase(context, parameter); - const [delimiter, explode] = getDelimeterAndExplode(parameter); + const [delimiter, explode] = getDelimiterAndExplode(parameter); return { ...base, wireName: parameter.serializedName, @@ -347,8 +347,8 @@ function emitHttpResponse( typeof statusCodes === "object" ? [(statusCodes as HttpStatusCodeRange).start] : statusCodes === "*" - ? ["default"] - : [statusCodes], + ? ["default"] + : [statusCodes], discriminator: "basic", type, contentTypes: response.contentTypes, diff --git a/packages/typespec-python/src/utils.ts b/packages/typespec-python/src/utils.ts index 7b25a68e26..d6976a0e4a 100644 --- a/packages/typespec-python/src/utils.ts +++ b/packages/typespec-python/src/utils.ts @@ -43,13 +43,13 @@ export function isAbstract( return (method.operation.bodyParam?.contentTypes.length ?? 0) > 1 && method.access !== "internal"; } -export function getDelimeterAndExplode( +export function getDelimiterAndExplode( parameter: SdkQueryParameter | SdkHeaderParameter, ): [string | undefined, boolean] { if (parameter.type.kind !== "array") return [undefined, false]; let delimiter: string | undefined = undefined; - let explode = false; - if (parameter.collectionFormat === "csv") { + let explode = parameter.kind === "query" && parameter.explode; + if (parameter.collectionFormat === "csv" || parameter.collectionFormat === "simple") { delimiter = "comma"; } else if (parameter.collectionFormat === "ssv") { delimiter = "space"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75e6e1a08f..6771273f62 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,7 +90,7 @@ importers: version: 0.35.3(@azure-tools/cadl-ranch-expect@0.15.1(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)))(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1))(@typespec/xml@0.59.0(@typespec/compiler@0.59.1)) '@azure-tools/typespec-autorest': specifier: ~0.45.0 - version: 0.45.0(jf7kycy44t4benafpfquc5zfzy) + version: 0.45.0(rpqariunvbmrtiqgjnzf2xlj7a) '@azure-tools/typespec-azure-core': specifier: ~0.45.0 version: 0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))) @@ -99,10 +99,10 @@ importers: version: 0.45.0(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) '@azure-tools/typespec-azure-rulesets': specifier: 0.45.0 - version: 0.45.0(qbuehpkdsyjme77wwr3jy24lee) + version: 0.45.0(mwjmldng43z2n3f3zahywksgry) '@azure-tools/typespec-client-generator-core': - specifier: 0.45.1 - version: 0.45.1(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) + specifier: 0.45.3 + version: 0.45.3(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) '@types/js-yaml': specifier: ~4.0.5 version: 4.0.5 @@ -249,8 +249,8 @@ packages: '@azure-tools/typespec-client-generator-core': ~0.45.0 '@typespec/compiler': ~0.59.0 - '@azure-tools/typespec-client-generator-core@0.45.1': - resolution: {integrity: sha512-C68pONnONncKlYjlU7JyxxS57NCLancPfoq0eDcaeXUcjFL34kkLKTE3VK0V6aBKBerAB5qOicsO9X81acFFCw==} + '@azure-tools/typespec-client-generator-core@0.45.3': + resolution: {integrity: sha512-o1E38DJnJ71ixK3jHTy42QgY1ztXPGEOhJjdzSb9aI0aXlqqBt0Klgg52RuBHBajQ+RI+nWtGLE+LJaVDSHAqw==} engines: {node: '>=18.0.0'} peerDependencies: '@azure-tools/typespec-azure-core': ~0.45.0 @@ -3706,11 +3706,11 @@ snapshots: - '@typespec/versioning' - supports-color - '@azure-tools/typespec-autorest@0.45.0(jf7kycy44t4benafpfquc5zfzy)': + '@azure-tools/typespec-autorest@0.45.0(rpqariunvbmrtiqgjnzf2xlj7a)': dependencies: '@azure-tools/typespec-azure-core': 0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))) '@azure-tools/typespec-azure-resource-manager': 0.45.0(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) - '@azure-tools/typespec-client-generator-core': 0.45.1(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) + '@azure-tools/typespec-client-generator-core': 0.45.3(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) '@typespec/compiler': 0.59.1 '@typespec/http': 0.59.0(@typespec/compiler@0.59.1) '@typespec/openapi': 0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)) @@ -3734,14 +3734,14 @@ snapshots: change-case: 5.4.4 pluralize: 8.0.0 - '@azure-tools/typespec-azure-rulesets@0.45.0(qbuehpkdsyjme77wwr3jy24lee)': + '@azure-tools/typespec-azure-rulesets@0.45.0(mwjmldng43z2n3f3zahywksgry)': dependencies: '@azure-tools/typespec-azure-core': 0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))) '@azure-tools/typespec-azure-resource-manager': 0.45.0(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) - '@azure-tools/typespec-client-generator-core': 0.45.1(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) + '@azure-tools/typespec-client-generator-core': 0.45.3(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1)) '@typespec/compiler': 0.59.1 - '@azure-tools/typespec-client-generator-core@0.45.1(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1))': + '@azure-tools/typespec-client-generator-core@0.45.3(@azure-tools/typespec-azure-core@0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))))(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/openapi@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1)))(@typespec/versioning@0.59.0(@typespec/compiler@0.59.1))': dependencies: '@azure-tools/typespec-azure-core': 0.45.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))(@typespec/rest@0.59.0(@typespec/compiler@0.59.1)(@typespec/http@0.59.0(@typespec/compiler@0.59.1))) '@typespec/compiler': 0.59.1 From b62131c86c57f53b3e27b6d0bb0e93e2d79bd40e Mon Sep 17 00:00:00 2001 From: tadelesh Date: Thu, 15 Aug 2024 18:07:21 +0800 Subject: [PATCH 2/5] update example related change --- .../typespec-python/scripts/regenerate.ts | 2 +- packages/typespec-python/src/lib.ts | 1 + .../generated_samples/basic.py | 34 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 packages/typespec-python/test/azure/generated/azure-example-basic/generated_samples/basic.py diff --git a/packages/typespec-python/scripts/regenerate.ts b/packages/typespec-python/scripts/regenerate.ts index 2afeadf74c..7f9d1da520 100644 --- a/packages/typespec-python/scripts/regenerate.ts +++ b/packages/typespec-python/scripts/regenerate.ts @@ -221,7 +221,7 @@ function addOptions(spec: string, generatedFolder: string, flags: RegenerateFlag if (flags.flavor === "unbranded") { options["company-name"] = "Unbranded"; } - options["examples-directory"] = toPosix(join(dirname(spec), "examples")); + options["examples-dir"] = toPosix(join(dirname(spec), "examples")); const configs = Object.entries(options).flatMap(([k, v]) => { return `--option @azure-tools/typespec-python.${k}=${v}`; }); diff --git a/packages/typespec-python/src/lib.ts b/packages/typespec-python/src/lib.ts index ba93d49efc..f50d34ae0c 100644 --- a/packages/typespec-python/src/lib.ts +++ b/packages/typespec-python/src/lib.ts @@ -41,6 +41,7 @@ const EmitterOptionsSchema: JSONSchemaType = { "generate-test": { type: "boolean", nullable: true }, "debug": { type: "boolean", nullable: true }, "flavor": { type: "string", nullable: true }, + "examples-dir": { type: "string", nullable: true, format: "absolute-path" }, }, required: [], }; diff --git a/packages/typespec-python/test/azure/generated/azure-example-basic/generated_samples/basic.py b/packages/typespec-python/test/azure/generated/azure-example-basic/generated_samples/basic.py new file mode 100644 index 0000000000..2c98b5f5ce --- /dev/null +++ b/packages/typespec-python/test/azure/generated/azure-example-basic/generated_samples/basic.py @@ -0,0 +1,34 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from specs.azure.example.basic import AzureExampleClient + +""" +# PREREQUISITES + pip install specs-azure-example-basic +# USAGE + python basic.py +""" + + +def main(): + client = AzureExampleClient() + + response = client.basic_action( + body={ + "arrayProperty": ["item"], + "modelProperty": {"enumProperty": "EnumValue1", "float32Property": 1.5, "int32Property": 1}, + "recordProperty": {"record": "value"}, + "stringProperty": "text", + }, + ) + print(response) + + +if __name__ == "__main__": + main() From 31ea678f3ee66c0cc7e69cd7fb864430dc8acce3 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Thu, 29 Aug 2024 17:16:18 +0800 Subject: [PATCH 3/5] support new spread logic change --- .../codegen/serializers/general_serializer.py | 4 ++-- packages/typespec-python/package.json | 2 +- packages/typespec-python/src/code-model.ts | 2 +- packages/typespec-python/src/http.ts | 15 +++++++++++---- packages/typespec-python/src/lib.ts | 1 + packages/typespec-python/src/types.ts | 6 ++---- packages/typespec-python/src/utils.ts | 3 +-- .../apiview_mapping_python.json | 7 ------- .../parameters-basic/apiview_mapping_python.json | 1 - .../apiview_mapping_python.json | 1 - .../parameters-spread/apiview_mapping_python.json | 7 ------- .../payload-multipart/apiview_mapping_python.json | 1 - .../typetest-union/apiview_mapping_python.json | 10 ---------- 13 files changed, 19 insertions(+), 41 deletions(-) diff --git a/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py b/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py index 69da33ee31..dd5315137f 100644 --- a/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py +++ b/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py @@ -182,12 +182,12 @@ def serialize_validation_file(self) -> str: def serialize_cross_language_definition_file(self) -> str: cross_langauge_def_dict = { f"{self.code_model.namespace}.models.{model.name}": model.cross_language_definition_id - for model in self.code_model.model_types + for model in self.code_model.public_model_types } cross_langauge_def_dict.update( { f"{self.code_model.namespace}.models.{enum.name}": enum.cross_language_definition_id - for enum in self.code_model.enums + for enum in self.code_model.enums if not enum.internal } ) cross_langauge_def_dict.update( diff --git a/packages/typespec-python/package.json b/packages/typespec-python/package.json index 81a7f7689a..d892c3976e 100644 --- a/packages/typespec-python/package.json +++ b/packages/typespec-python/package.json @@ -48,7 +48,7 @@ "@azure-tools/typespec-azure-core": ">=0.45.0 <1.0.0", "@azure-tools/typespec-azure-resource-manager": ">=0.45.0 <1.0.0", "@azure-tools/typespec-autorest": ">=0.45.0 <1.0.0", - "@azure-tools/typespec-client-generator-core": ">=0.45.3 <1.0.0", + "@azure-tools/typespec-client-generator-core": ">=0.45.4 <1.0.0", "@azure-tools/typespec-azure-rulesets": ">=0.45.0 <3.0.0", "@typespec/compiler": ">=0.59.1 <1.0.0", "@typespec/http": ">=0.59.0 <1.0.0", diff --git a/packages/typespec-python/src/code-model.ts b/packages/typespec-python/src/code-model.ts index 2affd518cf..31ca604591 100644 --- a/packages/typespec-python/src/code-model.ts +++ b/packages/typespec-python/src/code-model.ts @@ -227,7 +227,7 @@ export function emitCodeModel( } // loop through models and enums since there may be some orphaned models needs to be generated for (const model of sdkPackage.models) { - if (model.name === "" || (model.usage & UsageFlags.Spread) > 0) { + if (model.name === "" || (model.usage & UsageFlags.Spread) > 0 && (model.usage & UsageFlags.Input) === 0 && (model.usage & UsageFlags.Output) === 0) { continue; } if (!disableGenerationMap.has(model)) { diff --git a/packages/typespec-python/src/http.ts b/packages/typespec-python/src/http.ts index 3fb6afdb9a..881f3098a6 100644 --- a/packages/typespec-python/src/http.ts +++ b/packages/typespec-python/src/http.ts @@ -160,7 +160,7 @@ function emitHttpOperation( rootClient: SdkClientType, operationGroupName: string, operation: SdkHttpOperation, - method?: SdkServiceMethod, + method: SdkServiceMethod, ): Record { const responses: Record[] = []; const exceptions: Record[] = []; @@ -190,11 +190,14 @@ function emitHttpOperation( }; if ( result.bodyParameter && - operation.bodyParam?.type.kind === "model" && - (operation.bodyParam?.type.usage & UsageFlags.Spread) > 0 + isSpreadBody(operation.bodyParam) ) { result.bodyParameter["propertyToParameterName"] = {}; result.bodyParameter["defaultToUnsetSentinel"] = true; + // if body type is not only used for this spread body, but also used in other input/output, we should clone it, then change the type base to json + if ((result.bodyParameter.type.usage & UsageFlags.Input) > 0 || (result.bodyParameter.type.usage & UsageFlags.Output) > 0) { + result.bodyParameter.type = { ...result.bodyParameter.type, name: `${method.name}Request`}; + } result.bodyParameter.type.base = "json"; for (const property of result.bodyParameter.type.properties) { result.bodyParameter["propertyToParameterName"][property["wireName"]] = property["clientName"]; @@ -204,6 +207,10 @@ function emitHttpOperation( return result; } +function isSpreadBody(bodyParam: SdkBodyParameter | undefined): boolean { + return bodyParam?.type.kind === "model" && bodyParam.type !== bodyParam.correspondingMethodParams[0]?.type; +} + function emitFlattenedParameter( bodyParameter: Record, property: Record, @@ -310,7 +317,7 @@ function emitHttpBodyParameter( ): Record | undefined { if (bodyParam === undefined) return undefined; return { - ...emitParamBase(context, bodyParam, true), + ...emitParamBase(context, bodyParam), contentTypes: bodyParam.contentTypes, location: bodyParam.kind, clientName: bodyParam.isGeneratedName ? "body" : camelToSnakeCase(bodyParam.name), diff --git a/packages/typespec-python/src/lib.ts b/packages/typespec-python/src/lib.ts index f50d34ae0c..6704db56e5 100644 --- a/packages/typespec-python/src/lib.ts +++ b/packages/typespec-python/src/lib.ts @@ -16,6 +16,7 @@ export interface PythonEmitterOptions { "generate-test"?: boolean; "debug"?: boolean; "flavor"?: "azure"; + "examples-dir"?: string; } export interface PythonSdkContext diff --git a/packages/typespec-python/src/types.ts b/packages/typespec-python/src/types.ts index 6c69870cd4..0a598c375a 100644 --- a/packages/typespec-python/src/types.ts +++ b/packages/typespec-python/src/types.ts @@ -66,11 +66,10 @@ export function getSimpleTypeResult(result: Record): Record( context: PythonSdkContext, type: CredentialType | CredentialTypeUnion | Type | SdkType | MultiPartFileType, - fromBody = false, ): Record { switch (type.kind) { case "model": - return emitModel(context, type, fromBody); + return emitModel(context, type); case "union": return emitUnion(context, type); case "enum": @@ -239,7 +238,6 @@ function emitProperty( function emitModel( context: PythonSdkContext, type: SdkModelType, - fromBody: boolean, ): Record { if (isEmptyModel(type)) { return KnownTypes.any; @@ -257,7 +255,7 @@ function emitModel( discriminatedSubtypes: {} as Record>, properties: new Array>(), snakeCaseName: camelToSnakeCase(type.name), - base: type.isGeneratedName && fromBody ? "json" : "dpg", + base: "dpg", internal: type.access === "internal", crossLanguageDefinitionId: type.crossLanguageDefinitionId, usage: type.usage, diff --git a/packages/typespec-python/src/utils.ts b/packages/typespec-python/src/utils.ts index d6976a0e4a..a65bc25eed 100644 --- a/packages/typespec-python/src/utils.ts +++ b/packages/typespec-python/src/utils.ts @@ -90,9 +90,8 @@ export function getAddedOn( export function emitParamBase( context: PythonSdkContext, parameter: SdkParameter | SdkHttpParameter, - fromBody: boolean = false, ): ParamBase { - let type = getType(context, parameter.type, fromBody); + let type = getType(context, parameter.type); if (parameter.isApiVersionParam) { if (parameter.clientDefaultValue) { type = getSimpleTypeResult({ type: "constant", value: parameter.clientDefaultValue, valueType: type }); diff --git a/packages/typespec-python/test/azure/generated/azure-client-generator-core-access/apiview_mapping_python.json b/packages/typespec-python/test/azure/generated/azure-client-generator-core-access/apiview_mapping_python.json index 52c86eea8c..00f5a03148 100644 --- a/packages/typespec-python/test/azure/generated/azure-client-generator-core-access/apiview_mapping_python.json +++ b/packages/typespec-python/test/azure/generated/azure-client-generator-core-access/apiview_mapping_python.json @@ -1,16 +1,9 @@ { "CrossLanguagePackageId": "_Specs_.Azure.ClientGenerator.Core.Access", "CrossLanguageDefinitionId": { - "specs.azure.clientgenerator.core.access.models.AbstractModel": "_Specs_.Azure.ClientGenerator.Core.Access.RelativeModelInOperation.AbstractModel", - "specs.azure.clientgenerator.core.access.models.BaseModel": "_Specs_.Azure.ClientGenerator.Core.Access.RelativeModelInOperation.BaseModel", - "specs.azure.clientgenerator.core.access.models.InnerModel": "_Specs_.Azure.ClientGenerator.Core.Access.RelativeModelInOperation.InnerModel", - "specs.azure.clientgenerator.core.access.models.InternalDecoratorModelInInternal": "_Specs_.Azure.ClientGenerator.Core.Access.InternalOperation.InternalDecoratorModelInInternal", - "specs.azure.clientgenerator.core.access.models.NoDecoratorModelInInternal": "_Specs_.Azure.ClientGenerator.Core.Access.InternalOperation.NoDecoratorModelInInternal", "specs.azure.clientgenerator.core.access.models.NoDecoratorModelInPublic": "_Specs_.Azure.ClientGenerator.Core.Access.PublicOperation.NoDecoratorModelInPublic", - "specs.azure.clientgenerator.core.access.models.OuterModel": "_Specs_.Azure.ClientGenerator.Core.Access.RelativeModelInOperation.OuterModel", "specs.azure.clientgenerator.core.access.models.PublicDecoratorModelInInternal": "_Specs_.Azure.ClientGenerator.Core.Access.InternalOperation.PublicDecoratorModelInInternal", "specs.azure.clientgenerator.core.access.models.PublicDecoratorModelInPublic": "_Specs_.Azure.ClientGenerator.Core.Access.PublicOperation.PublicDecoratorModelInPublic", - "specs.azure.clientgenerator.core.access.models.RealModel": "_Specs_.Azure.ClientGenerator.Core.Access.RelativeModelInOperation.RealModel", "specs.azure.clientgenerator.core.access.models.SharedModel": "_Specs_.Azure.ClientGenerator.Core.Access.SharedModelInOperation.SharedModel", "specs.azure.clientgenerator.core.access.AccessClient.public_operation.no_decorator_in_public": "_Specs_.Azure.ClientGenerator.Core.Access.PublicOperation.noDecoratorInPublic", "specs.azure.clientgenerator.core.access.AccessClient.public_operation.public_decorator_in_public": "_Specs_.Azure.ClientGenerator.Core.Access.PublicOperation.publicDecoratorInPublic", diff --git a/packages/typespec-python/test/azure/generated/parameters-basic/apiview_mapping_python.json b/packages/typespec-python/test/azure/generated/parameters-basic/apiview_mapping_python.json index fc45432b56..3f5d96dd1c 100644 --- a/packages/typespec-python/test/azure/generated/parameters-basic/apiview_mapping_python.json +++ b/packages/typespec-python/test/azure/generated/parameters-basic/apiview_mapping_python.json @@ -1,7 +1,6 @@ { "CrossLanguagePackageId": "Parameters.Basic", "CrossLanguageDefinitionId": { - "parameters.basic.models.SimpleRequest": "Parameters.Basic.ImplicitBody.simple.Request.anonymous", "parameters.basic.models.User": "Parameters.Basic.ExplicitBody.User", "parameters.basic.BasicClient.explicit_body.simple": "Parameters.Basic.ExplicitBody.simple", "parameters.basic.BasicClient.implicit_body.simple": "Parameters.Basic.ImplicitBody.simple" diff --git a/packages/typespec-python/test/azure/generated/parameters-body-optionality/apiview_mapping_python.json b/packages/typespec-python/test/azure/generated/parameters-body-optionality/apiview_mapping_python.json index dc18c2eb6f..67bff97540 100644 --- a/packages/typespec-python/test/azure/generated/parameters-body-optionality/apiview_mapping_python.json +++ b/packages/typespec-python/test/azure/generated/parameters-body-optionality/apiview_mapping_python.json @@ -2,7 +2,6 @@ "CrossLanguagePackageId": "Parameters.BodyOptionality", "CrossLanguageDefinitionId": { "parameters.bodyoptionality.models.BodyModel": "Parameters.BodyOptionality.BodyModel", - "parameters.bodyoptionality.models.RequiredImplicitRequest": "Parameters.BodyOptionality.requiredImplicit.Request.anonymous", "parameters.bodyoptionality.BodyOptionalityClient.optional_explicit.set": "Parameters.BodyOptionality.OptionalExplicit.set", "parameters.bodyoptionality.BodyOptionalityClient.optional_explicit.omit": "Parameters.BodyOptionality.OptionalExplicit.omit", "parameters.bodyoptionality.BodyOptionalityClient.required_explicit": "Parameters.BodyOptionality.requiredExplicit", diff --git a/packages/typespec-python/test/azure/generated/parameters-spread/apiview_mapping_python.json b/packages/typespec-python/test/azure/generated/parameters-spread/apiview_mapping_python.json index 1e1f0ba40f..4ba87f686f 100644 --- a/packages/typespec-python/test/azure/generated/parameters-spread/apiview_mapping_python.json +++ b/packages/typespec-python/test/azure/generated/parameters-spread/apiview_mapping_python.json @@ -2,13 +2,6 @@ "CrossLanguagePackageId": "Parameters.Spread", "CrossLanguageDefinitionId": { "parameters.spread.models.BodyParameter": "Parameters.Spread.Model.BodyParameter", - "parameters.spread.models.SpreadAsRequestBodyRequest": "Parameters.Spread.Alias.spreadAsRequestBody.Request.anonymous", - "parameters.spread.models.SpreadAsRequestBodyRequest1": "Parameters.Spread.Model.spreadAsRequestBody.Request.anonymous", - "parameters.spread.models.SpreadAsRequestParameterRequest": "spreadAsRequestParameter.Request.anonymous", - "parameters.spread.models.SpreadCompositeRequestMixRequest": "spreadCompositeRequestMix.Request.anonymous", - "parameters.spread.models.SpreadParameterWithInnerAliasRequest": "spreadParameterWithInnerAlias.Request.anonymous", - "parameters.spread.models.SpreadParameterWithInnerModelRequest": "spreadParameterWithInnerModel.Request.anonymous", - "parameters.spread.models.SpreadWithMultipleParametersRequest": "spreadWithMultipleParameters.Request.anonymous", "parameters.spread.SpreadClient.model.spread_as_request_body": "Parameters.Spread.Model.spreadAsRequestBody", "parameters.spread.SpreadClient.model.spread_composite_request_only_with_body": "Parameters.Spread.Model.spreadCompositeRequestOnlyWithBody", "parameters.spread.SpreadClient.model.spread_composite_request_without_body": "Parameters.Spread.Model.spreadCompositeRequestWithoutBody", diff --git a/packages/typespec-python/test/azure/generated/payload-multipart/apiview_mapping_python.json b/packages/typespec-python/test/azure/generated/payload-multipart/apiview_mapping_python.json index 747b671dcb..a8229c80f2 100644 --- a/packages/typespec-python/test/azure/generated/payload-multipart/apiview_mapping_python.json +++ b/packages/typespec-python/test/azure/generated/payload-multipart/apiview_mapping_python.json @@ -2,7 +2,6 @@ "CrossLanguagePackageId": "Payload.MultiPart", "CrossLanguageDefinitionId": { "payload.multipart.models.Address": "Payload.MultiPart.Address", - "payload.multipart.models.AnonymousModelRequest": "anonymousModel.Request.anonymous", "payload.multipart.models.BinaryArrayPartsRequest": "Payload.MultiPart.BinaryArrayPartsRequest", "payload.multipart.models.ComplexHttpPartsModelRequest": "Payload.MultiPart.ComplexHttpPartsModelRequest", "payload.multipart.models.ComplexPartsRequest": "Payload.MultiPart.ComplexPartsRequest", diff --git a/packages/typespec-python/test/azure/generated/typetest-union/apiview_mapping_python.json b/packages/typespec-python/test/azure/generated/typetest-union/apiview_mapping_python.json index bf8eca1b0b..a4ddeed3ca 100644 --- a/packages/typespec-python/test/azure/generated/typetest-union/apiview_mapping_python.json +++ b/packages/typespec-python/test/azure/generated/typetest-union/apiview_mapping_python.json @@ -16,16 +16,6 @@ "typetest.union.models.GetResponse9": "Type.Union.get.Response.anonymous", "typetest.union.models.MixedLiteralsCases": "Type.Union.MixedLiteralsCases", "typetest.union.models.MixedTypesCases": "Type.Union.MixedTypesCases", - "typetest.union.models.SendRequest": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest1": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest2": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest3": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest4": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest5": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest6": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest7": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest8": "Type.Union.send.Request.anonymous", - "typetest.union.models.SendRequest9": "Type.Union.send.Request.anonymous", "typetest.union.models.StringAndArrayCases": "Type.Union.StringAndArrayCases", "typetest.union.models.StringExtensibleNamedUnion": "Type.Union.StringExtensibleNamedUnion", "typetest.union.UnionClient.strings_only.get": "Type.Union.StringsOnly.get", From 22a39b85fb3f69a3b1fae5b724b054f6043e9b8f Mon Sep 17 00:00:00 2001 From: tadelesh Date: Thu, 29 Aug 2024 17:18:58 +0800 Subject: [PATCH 4/5] changelog --- .../changes/explode_allowreserved-2024-7-29-17-18-49.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/explode_allowreserved-2024-7-29-17-18-49.md diff --git a/.chronus/changes/explode_allowreserved-2024-7-29-17-18-49.md b/.chronus/changes/explode_allowreserved-2024-7-29-17-18-49.md new file mode 100644 index 0000000000..d02c7c60a0 --- /dev/null +++ b/.chronus/changes/explode_allowreserved-2024-7-29-17-18-49.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@azure-tools/typespec-python" +--- + +support query `explode` and path `allowReserved`, also change the logic of generating spread body parameter \ No newline at end of file From 2dd7eb9d91c4de856b024bbc0994637ffa609c63 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Thu, 29 Aug 2024 17:35:18 +0800 Subject: [PATCH 5/5] format and lint --- .../codegen/serializers/general_serializer.py | 3 ++- packages/typespec-python/src/code-model.ts | 7 ++++++- packages/typespec-python/src/http.ts | 16 ++++++++-------- packages/typespec-python/src/types.ts | 2 +- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py b/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py index dd5315137f..2a2c1c24d6 100644 --- a/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py +++ b/packages/typespec-python/generator/pygen/codegen/serializers/general_serializer.py @@ -187,7 +187,8 @@ def serialize_cross_language_definition_file(self) -> str: cross_langauge_def_dict.update( { f"{self.code_model.namespace}.models.{enum.name}": enum.cross_language_definition_id - for enum in self.code_model.enums if not enum.internal + for enum in self.code_model.enums + if not enum.internal } ) cross_langauge_def_dict.update( diff --git a/packages/typespec-python/src/code-model.ts b/packages/typespec-python/src/code-model.ts index 31ca604591..90ee2f441c 100644 --- a/packages/typespec-python/src/code-model.ts +++ b/packages/typespec-python/src/code-model.ts @@ -227,7 +227,12 @@ export function emitCodeModel( } // loop through models and enums since there may be some orphaned models needs to be generated for (const model of sdkPackage.models) { - if (model.name === "" || (model.usage & UsageFlags.Spread) > 0 && (model.usage & UsageFlags.Input) === 0 && (model.usage & UsageFlags.Output) === 0) { + if ( + model.name === "" || + ((model.usage & UsageFlags.Spread) > 0 && + (model.usage & UsageFlags.Input) === 0 && + (model.usage & UsageFlags.Output) === 0) + ) { continue; } if (!disableGenerationMap.has(model)) { diff --git a/packages/typespec-python/src/http.ts b/packages/typespec-python/src/http.ts index 881f3098a6..c22c501700 100644 --- a/packages/typespec-python/src/http.ts +++ b/packages/typespec-python/src/http.ts @@ -188,15 +188,15 @@ function emitHttpOperation( crossLanguageDefinitionId: method?.crossLanguageDefintionId, samples: arrayToRecord(method?.operation.examples), }; - if ( - result.bodyParameter && - isSpreadBody(operation.bodyParam) - ) { + if (result.bodyParameter && isSpreadBody(operation.bodyParam)) { result.bodyParameter["propertyToParameterName"] = {}; result.bodyParameter["defaultToUnsetSentinel"] = true; // if body type is not only used for this spread body, but also used in other input/output, we should clone it, then change the type base to json - if ((result.bodyParameter.type.usage & UsageFlags.Input) > 0 || (result.bodyParameter.type.usage & UsageFlags.Output) > 0) { - result.bodyParameter.type = { ...result.bodyParameter.type, name: `${method.name}Request`}; + if ( + (result.bodyParameter.type.usage & UsageFlags.Input) > 0 || + (result.bodyParameter.type.usage & UsageFlags.Output) > 0 + ) { + result.bodyParameter.type = { ...result.bodyParameter.type, name: `${method.name}Request` }; } result.bodyParameter.type.base = "json"; for (const property of result.bodyParameter.type.properties) { @@ -354,8 +354,8 @@ function emitHttpResponse( typeof statusCodes === "object" ? [(statusCodes as HttpStatusCodeRange).start] : statusCodes === "*" - ? ["default"] - : [statusCodes], + ? ["default"] + : [statusCodes], discriminator: "basic", type, contentTypes: response.contentTypes, diff --git a/packages/typespec-python/src/types.ts b/packages/typespec-python/src/types.ts index 0a598c375a..d89dda5ad7 100644 --- a/packages/typespec-python/src/types.ts +++ b/packages/typespec-python/src/types.ts @@ -474,7 +474,7 @@ export function emitEndpointType( location: "endpointPath", implementation: getImplementation(context, param), clientDefaultValue: param.clientDefaultValue, - skipUrlEncoding: param.urlEncode === false, + skipUrlEncoding: param.urlEncode === false, // eslint-disable-line deprecation/deprecation }); context.__endpointPathParameters!.push(params.at(-1)!); }