Skip to content

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

Merged
l0lawrence merged 20 commits into
mainfrom
copilot/python-disable-typeddict-generation
Aug 4, 2026
Merged

[python] Add DPG TypedDict generation opt-out#11372
l0lawrence merged 20 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, and TypedDict-only output required the separate models-mode: typeddict value. This reworks the design so that models-mode only selects the model style and a dedicated generate-typeddict option controls TypedDict output independently.

  • Option design

    • models-mode selects the model style: dpg or none (msrest kept for back-compat)
    • generate-typeddict (default true) independently controls whether TypedDict overloads/models are generated
    • models-mode: typeddict is deprecated — it is still accepted (with a deprecation warning) and behaves as TypedDict-only, but callers should migrate to models-mode: none
  • Scenarios

    Goal Config
    DPG models + TypedDicts (default) models-mode: dpg
    TypedDicts only models-mode: none
    DPG models only (no TypedDicts) models-mode: dpg + generate-typeddict: false
  • Generator behavior

    • For TypeSpec input, models-mode: none + generate-typeddict: true is remapped internally to the existing TypedDict-only path, so all existing machinery is reused unchanged
    • In dpg mode with generate-typeddict: false, the TypedDict body overload is replaced by the pre-TypedDict raw-JSON overload (so the dict-body shape is still callable)
    • Swagger models-mode: none is left untouched (still produces no models)
    • Leaves the existing DPG model/binary overload behavior unchanged when TypedDicts are enabled
  • Tests

    • Adds OptionsDict coverage for the none → TypedDict-only remap, the generate-typeddict: false opt-out, and the models-mode: typeddict deprecation warning
    • Adds an integration test asserting models-mode: none maps to TypedDict-only overloads
  • Docs / config

    • Documents the option (covering both dpg and none) in the package README and generated emitter reference
    • Updates the generate-from-typespec skill guidance
    • Dogfoods the new path by switching the typetest-model-usage-typeddictonly test package to models-mode: none (byte-identical generated output)

Example:

options:
  "@typespec/http-client-python":
    # TypedDicts only
    models-mode: none
options:
  "@typespec/http-client-python":
    # DPG models without TypedDicts
    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: 9ba3373

@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 (default true) that controls TypedDict generation independently of models-mode. models-mode now toggles just dpg and none; the typeddict value is deprecated.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Python emitter diff

Baseline gh:18efd7b0b673711d85432924fce720362d3d87c9 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 thread packages/http-client-python/generator/pygen/preprocess/__init__.py Outdated
Comment thread packages/http-client-python/tests/unit/test_typeddict_overloads.py
l0lawrence and others added 3 commits July 27, 2026 12:07
…bodies

The skip condition sniffed for a combined-type member with base == typeddict,
but in models-mode: typeddict a spread body inserts the original base: dpg
model as its overload (it renders as a TypedDict via models-mode). That made
the sniff false, so the single-body JSON overload was wrongly kept, regressing
the prior behavior where the TypedDict overload replaced it.

Track this explicitly with a jsonOverloadReplacedByTypeddict flag set by
add_body_param_type wherever a TypedDict-style overload is inserted (both the
generate-typeddict dpg path via _insert_typeddict_overload and the
typeddict-only spread branch). add_overloads_for_body_param now checks the flag
instead of sniffing base == typeddict, so:
- models-mode: dpg (generate-typeddict on) and models-mode: typeddict both skip
  the single-body JSON overload, and
- only the generate-typeddict: false opt-out keeps it (pre-TypedDict behavior).

Addresses the PR reviewer comment.

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

Refactor the single-body JSON overload skip decision from a persisted
`jsonOverloadReplacedByTypeddict` YAML side-channel flag to an explicit
function parameter. `add_body_param_type` now returns whether a TypedDict-style
overload was inserted in place of the single-body raw-JSON overload, and the
single caller passes that to `add_overloads_for_body_param` as
`skip_single_body_json`. This removes the implicit cross-function coupling and
gives one source-of-truth decision point.

Pure refactor: generated output is byte-identical across all configs
(dpg+generate-typeddict on/off, models-mode: typeddict) - verified by
regenerating parameters/body-optionality both ways and diffing all files.

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

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

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

@iscai-msft iscai-msft left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i think one thing we can do is remove typeddict from models-mode. models-mode would just toggle dpg and none (and msrest for backcompat, but let's ignore that). We would deprecate models-mode=typeddict and the different scenarios would look like

  1. default (by default models-mode=dpg and generate-typeddicts=true
  2. td only (just specify models-mode=none in tspconfig
  3. no td (specify generate-typeddicts=false in tspconfig

Comment thread packages/http-client-python/emitter/src/lib.ts
l0lawrence and others added 3 commits July 28, 2026 13:47
… models-mode none

Rework the DPG TypedDict opt-out so models-mode only toggles dpg/none
(msrest kept for back-compat) and TypedDict output is controlled by the
generate-typeddict option. models-mode: none now remaps internally to the
typeddict-only path, reusing all existing machinery; models-mode: typeddict
is deprecated (still accepted with a warning). Update option docs, changelog,
SKILL, and regen-common dogfooding, and clarify internal preprocess comments.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 511e3e1d-5321-4281-8d91-d5be7a28d81d
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 511e3e1d-5321-4281-8d91-d5be7a28d81d
Comment thread packages/http-client-python/generator/pygen/preprocess/__init__.py
Comment thread packages/http-client-python/generator/pygen/__init__.py Outdated
Comment thread packages/http-client-python/generator/pygen/__init__.py Outdated
Comment thread packages/http-client-python/tests/unit/test_typeddict_overloads.py Outdated
Comment thread packages/http-client-python/README.md Outdated
- Remove synthetic internal `models-mode: typeddict`; represent the
  deprecated value as `models-mode: none` + `generate-typeddict: true`,
  and drive TypedDict-only behavior via a `generate_typeddict_only`
  helper instead of a fake models-mode.
- Replace generic `**kwargs` in the `_plugin` test helper with an
  explicit `generate_typeddict: bool` parameter.
- Drop msrest from the models-mode ValueError help text (back-compat only).
- Reword the `generate-typeddict` description: it adds TypedDict typing
  for JSON dict input, not an extra request-body overload.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8b26a94-682b-4350-a424-97093fd1c183
@l0lawrence
l0lawrence requested a review from markcowl as a code owner August 3, 2026 19:30
l0lawrence and others added 4 commits August 3, 2026 12:35
…ecated

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8b26a94-682b-4350-a424-97093fd1c183
…ization comment

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8b26a94-682b-4350-a424-97093fd1c183
… in is_typeddict_only

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8b26a94-682b-4350-a424-97093fd1c183
…dels-mode check

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8b26a94-682b-4350-a424-97093fd1c183

@msyyc msyyc 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.

Looks good to me. Approved but better to wait for @iscai-msft's approval too in case of more review comments.

@l0lawrence
l0lawrence added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit 5a8b1e2 Aug 4, 2026
45 checks passed
@l0lawrence
l0lawrence deleted the copilot/python-disable-typeddict-generation branch August 4, 2026 16:23
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

6 participants