diff --git a/.chronus/changes/python-fix-client-default-value-serialization-2026-4-29-10-23-0.md b/.chronus/changes/python-fix-client-default-value-serialization-2026-4-29-10-23-0.md new file mode 100644 index 00000000000..3465d555a03 --- /dev/null +++ b/.chronus/changes/python-fix-client-default-value-serialization-2026-4-29-10-23-0.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-client-python" +--- + +Fix serialization regression where `@clientDefaultValue` defaults on model properties were no longer included in the request body. Defaults are again materialized in the model's data dictionary at construction time so they are sent on the wire, while the attribute-access fallback for unset fields is preserved. diff --git a/eng/emitters/pipelines/templates/stages/emitter-stages.yml b/eng/emitters/pipelines/templates/stages/emitter-stages.yml index 2b0a5721387..c072e169096 100644 --- a/eng/emitters/pipelines/templates/stages/emitter-stages.yml +++ b/eng/emitters/pipelines/templates/stages/emitter-stages.yml @@ -130,35 +130,11 @@ stages: PackagePath: ${{ parameters.PackagePath }} LanguageShortName: ${{ parameters.LanguageShortName }} BuildArtifactName: build_artifacts_${{ parameters.LanguageShortName }} - NodeVersion: 20.x + NodeVersion: 22.x Os: linux EmitArtifacts: true # Emit artifacts only for the first job PythonVersion: ${{ parameters.PythonVersion }} RunSDLTools: true - - template: /eng/emitters/pipelines/templates/jobs/build-job.yml - parameters: - BuildPrereleaseVersion: ${{ parameters.BuildPrereleaseVersion }} - UseTypeSpecNext: ${{ parameters.UseTypeSpecNext }} - Publish: ${{ parameters.Publish }} - AdditionalInitializeSteps: ${{ parameters.AdditionalInitializeSteps }} - Packages: ${{ parameters.Packages }} - PackagePath: ${{ parameters.PackagePath }} - LanguageShortName: ${{ parameters.LanguageShortName }} - NodeVersion: 22.x - Os: linux - PythonVersion: ${{ parameters.PythonVersion }} - - template: /eng/emitters/pipelines/templates/jobs/build-job.yml - parameters: - BuildPrereleaseVersion: ${{ parameters.BuildPrereleaseVersion }} - UseTypeSpecNext: ${{ parameters.UseTypeSpecNext }} - Publish: ${{ parameters.Publish }} - AdditionalInitializeSteps: ${{ parameters.AdditionalInitializeSteps }} - Packages: ${{ parameters.Packages }} - PackagePath: ${{ parameters.PackagePath }} - LanguageShortName: ${{ parameters.LanguageShortName }} - NodeVersion: 20.x - Os: windows - PythonVersion: ${{ parameters.PythonVersion }} - template: /eng/emitters/pipelines/templates/jobs/build-job.yml parameters: BuildPrereleaseVersion: ${{ parameters.BuildPrereleaseVersion }} @@ -175,7 +151,7 @@ stages: - template: /eng/emitters/pipelines/templates/jobs/detect-api-changes.yml parameters: LanguageShortName: ${{ parameters.LanguageShortName }} - DependsOn: Build_linux_20 + DependsOn: Build_linux_22 BuildArtifactName: build_artifacts_${{ parameters.LanguageShortName }} Artifacts: - ${{ each package in parameters.Packages }}: @@ -204,35 +180,13 @@ stages: TestArgs: ${{ parameters.UnitTestArgs }} LanguageShortName: ${{ parameters.LanguageShortName }} BuildArtifactName: build_artifacts_${{ parameters.LanguageShortName }} - NodeVersion: 20.x + NodeVersion: 22.x Os: linux EmitArtifacts: true # Emit artifacts only for the first job CadlRanchName: ${{ parameters.CadlRanchName }} # only needed for first job EnableCadlRanchReport: ${{ parameters.EnableCadlRanchReport }} PythonVersion: ${{ parameters.PythonVersion }} UseTypeSpecNext: ${{ parameters.UseTypeSpecNext }} - - template: /eng/emitters/pipelines/templates/jobs/test-job.yml - parameters: - AdditionalInitializeSteps: ${{ parameters.AdditionalInitializeSteps }} - PackagePath: ${{ parameters.PackagePath }} - TestArgs: ${{ parameters.UnitTestArgs }} - LanguageShortName: ${{ parameters.LanguageShortName }} - BuildArtifactName: build_artifacts_${{ parameters.LanguageShortName }} - NodeVersion: 22.x - Os: linux - PythonVersion: ${{ parameters.PythonVersion }} - UseTypeSpecNext: ${{ parameters.UseTypeSpecNext }} - - template: /eng/emitters/pipelines/templates/jobs/test-job.yml - parameters: - AdditionalInitializeSteps: ${{ parameters.AdditionalInitializeSteps }} - PackagePath: ${{ parameters.PackagePath }} - TestArgs: ${{ parameters.UnitTestArgs }} - LanguageShortName: ${{ parameters.LanguageShortName }} - BuildArtifactName: build_artifacts_${{ parameters.LanguageShortName }} - NodeVersion: 20.x - Os: windows - PythonVersion: ${{ parameters.PythonVersion }} - UseTypeSpecNext: ${{ parameters.UseTypeSpecNext }} - template: /eng/emitters/pipelines/templates/jobs/test-job.yml parameters: AdditionalInitializeSteps: ${{ parameters.AdditionalInitializeSteps }} diff --git a/eng/emitters/pipelines/templates/steps/test-step.yml b/eng/emitters/pipelines/templates/steps/test-step.yml index f2cdf86217c..c61b148b7fe 100644 --- a/eng/emitters/pipelines/templates/steps/test-step.yml +++ b/eng/emitters/pipelines/templates/steps/test-step.yml @@ -13,7 +13,7 @@ parameters: # Node version - name: NodeVersion type: string - default: "20.x" + default: "22.x" # Arguments needed to run tests - name: TestArgs diff --git a/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 b/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 index 258b741a8dd..19f8f222acf 100644 --- a/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 +++ b/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 @@ -642,6 +642,14 @@ class Model(_MyMutableMapping): if v is not None } ) + # Apply client default values for fields the caller didn't set so that + # defaults are part of `_data` and therefore included during serialization. + for rf in self._attr_to_rest_field.values(): + if rf._default is _UNSET: + continue + if rf._rest_name in dict_to_pass: + continue + dict_to_pass[rf._rest_name] = _create_value(rf, rf._default) super().__init__(dict_to_pass) def _init_from_xml(self, element: ET.Element) -> dict[str, typing.Any]: diff --git a/packages/http-client-python/package-lock.json b/packages/http-client-python/package-lock.json index a6129262122..ff3a016fe9e 100644 --- a/packages/http-client-python/package-lock.json +++ b/packages/http-client-python/package-lock.json @@ -17,7 +17,7 @@ "tsx": "^4.21.0" }, "devDependencies": { - "@azure-tools/azure-http-specs": "0.1.0-alpha.39", + "@azure-tools/azure-http-specs": "0.1.0-alpha.40-dev.12", "@azure-tools/typespec-autorest": "~0.67.0", "@azure-tools/typespec-azure-core": "~0.67.0", "@azure-tools/typespec-azure-resource-manager": "~0.67.0", @@ -66,25 +66,25 @@ } }, "node_modules/@azure-tools/azure-http-specs": { - "version": "0.1.0-alpha.39", - "resolved": "https://registry.npmjs.org/@azure-tools/azure-http-specs/-/azure-http-specs-0.1.0-alpha.39.tgz", - "integrity": "sha512-l9d2Y+B7QBi20ocDJEGO7NpvpCePvdw2ALz1RHAPWBOD0tPUBXUQ4WF1zUC199awz8hQysNRM9jm8x+eoUvjEQ==", + "version": "0.1.0-alpha.40-dev.12", + "resolved": "https://registry.npmjs.org/@azure-tools/azure-http-specs/-/azure-http-specs-0.1.0-alpha.40-dev.12.tgz", + "integrity": "sha512-N2d7IVgA5tw4yE2FYWt6vz55TcNcQgdReFBELvbxQhKmsDQZFwc2lh6euVC2P/MpSkeXMXJMnnkuJ1KH/DLxFA==", "dev": true, "license": "MIT", "dependencies": { - "@typespec/spec-api": "^0.1.0-alpha.14", - "@typespec/spector": "^0.1.0-alpha.25" + "@typespec/spec-api": "^0.1.0-alpha.14 || >=0.1.0-alpha.15-dev <0.1.0-alpha.15", + "@typespec/spector": "^0.1.0-alpha.25 || >=0.1.0-alpha.26-dev <0.1.0-alpha.26" }, "engines": { - "node": ">=20.0.0" + "node": ">=22.0.0" }, "peerDependencies": { - "@azure-tools/typespec-azure-core": "^0.67.0", + "@azure-tools/typespec-azure-core": "^0.67.1 || >=0.68.0-dev <0.68.0", "@typespec/compiler": "^1.11.0", "@typespec/http": "^1.11.0", - "@typespec/rest": "^0.81.0", - "@typespec/versioning": "^0.81.0", - "@typespec/xml": "^0.81.0" + "@typespec/rest": "^0.81.0 || >=0.82.0-dev <0.82.0", + "@typespec/versioning": "^0.81.0 || >=0.82.0-dev <0.82.0", + "@typespec/xml": "^0.81.0 || >=0.82.0-dev <0.82.0" } }, "node_modules/@azure-tools/typespec-autorest": { @@ -114,9 +114,9 @@ } }, "node_modules/@azure-tools/typespec-azure-core": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.67.0.tgz", - "integrity": "sha512-6DO/fOlVihMlPG0oDXrgURf5MNF4iBzPx5SMA5aaFDx/fW6MjiD+TN9Yy9O+l9mVNh1XaEMjhjA8/lmnHZ/U0g==", + "version": "0.67.1", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.67.1.tgz", + "integrity": "sha512-HBvigwr8Ub7rsg4RDpTO3WTHS+CIqAw32X3RzxsDNb8NfLoSLSZDANz05VPiDTzAXO7eMfEP42RXkKPV0tlZLg==", "dev": true, "license": "MIT", "engines": { diff --git a/packages/http-client-python/package.json b/packages/http-client-python/package.json index 644950c2daf..6c4dfa859d1 100644 --- a/packages/http-client-python/package.json +++ b/packages/http-client-python/package.json @@ -103,7 +103,7 @@ "@azure-tools/typespec-azure-resource-manager": "~0.67.0", "@azure-tools/typespec-azure-rulesets": "~0.67.0", "@azure-tools/typespec-client-generator-core": "~0.67.0", - "@azure-tools/azure-http-specs": "0.1.0-alpha.39", + "@azure-tools/azure-http-specs": "0.1.0-alpha.40-dev.12", "@typespec/compiler": "^1.11.0", "@typespec/http": "^1.11.0", "@typespec/openapi": "^1.11.0",