Skip to content

[python] Add DPG TypedDict generation opt-out#11372

Draft
l0lawrence with Copilot wants to merge 7 commits into
mainfrom
copilot/python-disable-typeddict-generation
Draft

[python] Add DPG TypedDict generation opt-out#11372
l0lawrence with Copilot wants to merge 7 commits into
mainfrom
copilot/python-disable-typeddict-generation

Conversation

Copilot AI commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

DPG mode in the Python emitter always generated TypedDict request-body overloads, with no tspconfig escape hatch. This adds an explicit emitter option so callers can keep models-mode: dpg while disabling automatic TypedDict generation.

  • New emitter option

    • Adds generate-typeddict to @typespec/http-client-python
    • Defaults to true to preserve current behavior
    • Can be set in tspconfig.yaml to opt out of DPG TypedDict auto-generation
  • Generator behavior

    • Updates Python generator options to recognize generate-typeddict
    • In DPG mode, skips creating TypedDict body overload copies when the option is false
    • Leaves the existing DPG model/binary overload behavior unchanged
  • Tests

    • Adds focused coverage for the new option default
    • Adds regression coverage that generate-typeddict: false suppresses TypedDict copy generation in DPG mode
  • Docs

    • Documents the new option in the package README and generated emitter reference

Example:

options:
  "@typespec/http-client-python":
    models-mode: dpg
    generate-typeddict: false

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added meta:website TypeSpec.io updates emitter:client:python Issue for the Python client emitter: @typespec/http-client-python labels Jul 23, 2026
Copilot AI changed the title [WIP] Add option to disable typeddict auto-generation in dpg mode [python] Add DPG TypedDict generation opt-out Jul 23, 2026
Copilot AI requested a review from l0lawrence July 23, 2026 15:57
@l0lawrence

Copy link
Copy Markdown
Member

@copilot if we dont generate the typeddict overload we should generate the JSON overload

Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com>

Copilot AI commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot if we dont generate the typeddict overload we should generate the JSON overload

Addressed in 3f8f519. I added regression coverage that generate-typeddict: false keeps the flattened JSON spread-body overload (alongside the binary overload) without emitting a TypedDict copy.

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 025eceb

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/http-client-python
Show changes

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

Add a generate-typeddict emitter option to opt out of generating TypedDict request-body overloads in models-mode: dpg. Defaults to true; set it to false to disable the DPG TypedDict overloads.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Python emitter diff

Baseline gh:42feb121b9cc8edbd7a2aee2367c3c3d17f9bf33 vs this PR.

No changes to generated output.

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

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

l0lawrence and others added 3 commits July 24, 2026 12:37
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 753f3788-98a9-4e39-8655-9c6a3ce90536
…alse

When generate-typeddict: false, the opt-out now performs a true revert to
pre-TypedDict behavior by restoring the standalone raw-JSON dict @overload
(and JSON in the impl Union) for both the explicit/model body path and the
spread path, instead of only dropping the TypedDict overload.

- add_overloads_for_body_param: only skip the single-body JSON overload when
  a TypedDict overload was actually inserted; otherwise keep it.
- add_body_param_type: insert the raw-JSON (any-object) overload via new
  _insert_json_overload helper when TypedDict generation is disabled.
- Update test_typeddict_overloads.py opt-out tests to assert the restored
  [model, JSON, binary] / flattened+JSON+binary overload sets.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 753f3788-98a9-4e39-8655-9c6a3ce90536

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.

Pull request overview

This PR adds a new @typespec/http-client-python emitter option (generate-typeddict) to let users opt out of generating TypedDict request-body overloads while keeping models-mode: dpg, preserving default behavior (true) for back-compat.

Changes:

  • Added generate-typeddict option surfaced via the emitter’s TypeScript options schema and the Python generator’s OptionsDict defaults.
  • Updated the Python preprocess plugin to conditionally insert TypedDict vs raw-JSON overload types based on generate-typeddict.
  • Added unit tests and updated docs/reference material to cover and describe the new option.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
website/src/content/docs/docs/emitters/clients/http-client-python/reference/emitter.md Documents the new generate-typeddict option in the website emitter reference.
packages/http-client-python/tests/unit/test_typeddict_overloads.py Adds regression tests for disabling TypedDict overload generation in DPG mode.
packages/http-client-python/tests/unit/test_options_dict.py Adds unit coverage for the option defaulting to true and being settable to false.
packages/http-client-python/README.md Documents the new generate-typeddict option in the package README.
packages/http-client-python/generator/pygen/preprocess/init.py Implements the opt-out behavior and adjusts overload generation logic.
packages/http-client-python/generator/pygen/init.py Adds the option default (generate-typeddict: True) to OptionsDict.
packages/http-client-python/emitter/src/lib.ts Adds the option to the TypeScript emitter options interface and JSON schema.
.chronus/changes/python-disable-typeddict-generation-2026-7-24-12-59-0.md Adds a Chronus changelog entry for the new feature.

Comment on lines +97 to +102
# When a TypedDict overload was inserted, it replaces the single-body JSON
# overload, so skip it. When TypedDict generation is disabled, no TypedDict
# overload exists and we keep the single-body raw-JSON overload (pre-TypedDict
# behavior) by falling through.
if any(t.get("base") == "typeddict" for t in body_parameter["type"]["types"]):
continue
Comment on lines +125 to +150
def test_spread_body_opt_out_keeps_json_overload():
"""Spread bodies revert to pre-TypedDict: flattened + single-body JSON + binary."""
plugin = _plugin("dpg", **{"generate-typeddict": False})
spread_body = _json_spread_body_parameter("CreateRequest", "Contoso.Widget")
yaml_data = {
"name": "create",
"bodyParameter": spread_body,
"parameters": [_content_type_param()],
"overloads": [],
"responses": [],
"exceptions": [],
}
code_model = {"types": [spread_body["type"]]}

plugin.add_body_param_type(code_model, spread_body)
add_overloads_for_body_param(yaml_data)

assert spread_body["type"]["type"] == "combined"
assert spread_body["type"]["types"][0]["base"] == "json"
assert spread_body["type"]["types"][1] == {"type": "binary"}
assert len(yaml_data["overloads"]) == 3
json_overloads = [o for o in yaml_data["overloads"] if o["bodyParameter"]["type"].get("base") == "json"]
# Both a flattened (keyword params) overload AND a single-body raw-JSON overload.
assert any(o["bodyParameter"].get("flattened") for o in json_overloads)
assert any(not o["bodyParameter"].get("flattened") for o in json_overloads)
assert not any(t for t in code_model["types"] if t.get("base") == "typeddict")
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 meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[python] tspconfig to disable typeddict auto-generation

3 participants