Skip to content

[http-client-python] Escape generated discriminator string literals - #12342

Open
Yuchao Yan (msyyc) wants to merge 2 commits into
mainfrom
users/msyyc/python-discriminator-string-literals
Open

Yuchao Yan (msyyc) wants to merge 2 commits into
mainfrom
users/msyyc/python-discriminator-string-literals

Conversation

@msyyc

@msyyc Yuchao Yan (msyyc) commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fix Python string-literal generation described in this report.

  • Use Python literal serialization for string constants and discriminator class arguments instead of adding quotes around specification values.
  • Apply the same fix to discriminator initialization and JSON input templates.
  • Preserve Python expressions and literal escapes through JSON template rendering. Keep code examples unwrapped and escape them for their enclosing docstrings.
  • Add regression coverage for quotes, backslashes, newlines, control characters, Unicode, and expression-like text. Check literal AST nodes, annotations, repeated model construction, discriminator selection, serialization, and shared enum generation.
  • Update two TypedDict expectations for the equivalent quotation style and add a fix changelog.

Validation

  • Python emitter build, package formatting checks, and emitter/generator lint passed.
  • Emitter tests: 35 passed.
  • Related Python generator tests: 165 passed, 1 deselected.
  • New regression file: 52 passed. The initial fix reproduced 20 failures against an unchanged generator snapshot. The follow-up reproduced five final-template failures and three emitted-documentation failures before their respective fixes.
  • Generated and imported a Python SDK from a minimal TypeSpec service. Confirmed exact discriminator values in annotations, repeated construction, serialization, and discriminator dispatch.
  • Generated JSON-mode sync and async SDKs, parsed their operation docstrings, and verified four final code examples preserve the exact discriminator value.

The deselected test, test_models_mode_typeddict_does_not_write_empty_models_folder, fails identically against the unchanged baseline. It is unrelated to string serialization and is not changed here. Local Python runtime validation used Python 3.13.

Repository-wide pnpm format reports a parse error in the unchanged packages/http-specs/specs/type/union/discriminated/extends/main.tsp. Python emitter package formatting checks pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ecfba725-b27d-416c-95a6-bc48a498ca8f
@pkg-pr-new

pkg-pr-new Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-python@12342

commit: 599403e

@msyyc
Yuchao Yan (msyyc) marked this pull request as draft October 22, 2026 05:53
@github-actions

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • ✅ @typespec/http-client-python
Show changes

@typespec/http-client-python - fix ✏️

Escape string literals in generated Python discriminator declarations, initializers, and templates to preserve specification values as data.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Targeted verification confirms that downstream template rendering still corrupts escaped values and can produce invalid Python examples.

1 open issue
What changed in this PR

This PR updates the Python client generator to serialize specification strings as Python literals, preserving special characters and treating expression-like text as data.

Changes:

  • Replace manual quoting in string declarations, discriminator arguments, initializers, and template values.
  • Add regression tests for literal preservation and generated model behavior; adjust TypedDict quotation expectations.
  • Add a Python emitter fix changelog.
File Description
packages/​http-client-python/​tests/​unit/​test_typeddict.py Update two expectations for equivalent literal quoting.
packages/​http-client-python/​tests/​unit/​test_string_literals.py Add special-character and discriminator regression coverage.
packages/​http-client-python/​generator/​pygen/​codegen/​serializers/​model_serializer.py Escape discriminator initializers and class arguments.
packages/​http-client-python/​generator/​pygen/​codegen/​models/​primitive_types.py Serialize string declarations with repr.
packages/​http-client-python/​generator/​pygen/​codegen/​models/​model_type.py Escape discriminator values in template representations.
.chronus/​changes/​python-discriminator-string-literals-2026-10-22.md Document the Python string-literal fix.

Review effort: Balanced

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Python emitter diff

Baseline gh:721154b2ab55bfc78ab4850e86c40487f66241f2 vs this PR.

Diff summary: 1174 file(s), +5813 / -5821

Rendered diff: inline on the run summary, or the emitter-diff-html artifact.

Informational check (eng/emitter-diff); does not block the PR.

@azure-sdk-automation

azure-sdk-automation Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ecfba725-b27d-416c-95a6-bc48a498ca8f
@msyyc

Yuchao Yan (msyyc) commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

CI investigation: the optional Azure/typespec-azure integration check fails on both the original and follow-up heads, outside this Python change. Latest run: https://github.com/microsoft/typespec/actions/runs/39734024339/job/119675416698. The downstream playground imports registerMonacoDefaultWorkersForVite from @typespec/playground, but the current API is exported from @typespec/playground/vite/workers. The downstream import needs updating; this PR does not change playground exports or bypass the check. All other current-head checks have now passed. Tracked in Azure/typespec-azure#5806; monitoring continues.

{% for template_line in example_template %}
{% if template_line %}
{% set wrap_amount = (template_line | length) - (template_line.lstrip() | length) + 10 %}
{{ wrap_string(template_line, wrapstring='\n' + " " * wrap_amount, width=(95 - wrap_amount)) }}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iscai-msft I remember the code has special effect for specific SDK doc string, so not sure whether it is ok to remove the logic

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Complete model rendering still produces invalid Python for triple-quote discriminator values, which the hand-built regression does not exercise.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment on lines +153 to +158
source = "\n".join(
[
"class Base(_Model):",
" __mapping__ = {}",
' kind: str = rest_discriminator(name="kind")',
serializer.declare_model(model),

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:python Issue for the Python client emitter: @typespec/http-client-python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants