Skip to content

[python] add typeddict models-mode for Python HTTP client emitter#10439

Open
iscai-msft wants to merge 72 commits into
microsoft:mainfrom
iscai-msft:python/addTypedDict
Open

[python] add typeddict models-mode for Python HTTP client emitter#10439
iscai-msft wants to merge 72 commits into
microsoft:mainfrom
iscai-msft:python/addTypedDict

Conversation

@iscai-msft

@iscai-msft iscai-msft commented Apr 21, 2026

Copy link
Copy Markdown
Member

fixes #8800

Add a new 'typeddict' value for the models-mode option that generates Python TypedDict classes instead of DPG model classes. Key features:

  • TypedDict classes with Required[T]/NotRequired[T] annotations
  • TypedDict inheritance for non-discriminated models
  • Discriminated models: Union of leaf TypedDicts, no abstract base class
  • Input-only: operations accept TypedDict input, return dict output
  • Wire names used as TypedDict keys
  • _model_base.py still generated for serialization utilities

Add a new 'typeddict' value for the models-mode option that generates
Python TypedDict classes instead of DPG model classes. Key features:

- TypedDict classes with Required[T]/NotRequired[T] annotations
- TypedDict inheritance for non-discriminated models
- Discriminated models: Union of leaf TypedDicts, no abstract base class
- Input-only: operations accept TypedDict input, return dict output
- Wire names used as TypedDict keys
- _model_base.py still generated for serialization utilities

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:python Issue for the Python client emitter: @typespec/http-client-python label Apr 21, 2026
@pkg-pr-new

pkg-pr-new Bot commented Apr 21, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 32a4836

@github-actions

github-actions Bot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/http-client-python
Show changes

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

[python] Always generate TypedDict typing hints for input models in the types.py file, and named union aliases in the _unions.py file

@azure-sdk

azure-sdk commented Apr 21, 2026

Copy link
Copy Markdown
Collaborator

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

iscai-msft and others added 12 commits April 21, 2026 14:37
- TypedDictModelType returns 'JSON' for response type annotations
- Response.type_annotation/docstring passes is_response=True
- Typeddict deserialization uses response.json() directly
- Removed NotRequired from TypedDictModelSerializer (total=False handles it)
- Updated mock API tests to verify JSON dict responses

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add client/naming typeddict variant to regenerate-common.ts
- Create test_client_naming_typeddict.py with 11 tests verifying TypedDict
  uses wire names (defaultName, wireName) not client names
- Tests cover: ClientNameModel, LanguageClientNameModel,
  ClientNameAndJsonEncodedNameModel, ClientModel, PythonModel

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TypedDict is already JSON, so the MutableMapping[str, Any] overload
is unnecessary. Only keep TypedDict model + IO[bytes] overloads.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Typeddict mode uses response.json() directly, so _deserialize is never
called. Skip importing it to avoid W0611 unused-import lint warning.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove unused MutableMapping/Any imports from TypedDictModelType.imports()
- Skip _deserialize import in paging_operation.py for typeddict mode

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TypedDictModelType returns 'JSON' for response type annotations but
never defined the JSON = MutableMapping[str, Any] type alias, causing
NameError at runtime.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@iscai-msft iscai-msft force-pushed the python/addTypedDict branch from 34e0cda to 95db199 Compare April 29, 2026 15:39
@msyyc

msyyc commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

I invoked workflow to generate code diff for this PR: Azure/azure-sdk-for-python#47346 for better review.

iscai-msft and others added 2 commits June 4, 2026 15:19
When multiple namespaces import 'types', the second import shadows the
first causing mypy errors ('Name types already defined') and runtime
failures ('Name types.X is not defined').

Add get_unique_types_alias() (mirrors get_unique_models_alias) to
generate unique aliases like _types, _types_models1, _types_models2.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@iscai-msft iscai-msft force-pushed the python/addTypedDict branch from d6eb5ab to 4c0a3ac Compare June 4, 2026 20:09
In types.py (TypedDict definitions), use the JSON wire type instead of
rich Python types for properties:
- datetime.datetime → str
- datetime.date → str
- datetime.time → str
- datetime.timedelta → str
- datetime.datetime (unix) → int
- decimal.Decimal → float
- bytes → str

This follows the principle that TypedDicts represent the wire/JSON shape
of the data. Rich types like datetime are still used in model classes
and operation signatures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@iscai-msft iscai-msft requested review from johanste and msyyc June 5, 2026 20:26
@iscai-msft

Copy link
Copy Markdown
Member Author

can people take a look at the regeneration, it automatically updates in the pr that @msyyc linked, linking here again for ease of access. You can pay specific attention to tests with date times etc, I now make sure the TD include the serialized value instead of the client value. would be great to get this PR in, at least as a first step, and to keep improving if / when we run into issues, cc @kashifkhan

@msyyc

msyyc commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

There is new file named types.py for each package but in some packages like https://github.com/Azure/azure-sdk-for-python/pull/47346/changes#r3379542204, the file is not referred by other model/operation, is it expected?

@msyyc

msyyc commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@msyyc

msyyc commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@iscai-msft iscai-msft requested a review from kashifkhan as a code owner June 22, 2026 17:47
iscai-msft and others added 4 commits June 22, 2026 15:28
# Conflicts:
#	packages/http-client-python/generator/pygen/preprocess/__init__.py
- Add crossLanguageDefinitionId-based dedup to dpg model TypedDict creation
  (prevents duplicate TypedDict classes when multiple operations share the same body model)
- Dedup typeddict_models in TypesSerializer: prefer dpg model over typeddict copy
  when both exist with the same crossLanguageDefinitionId

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

Copy link
Copy Markdown
Member Author

https://github.com/Azure/azure-sdk-for-python/pull/47346/changes#r3379640848

this is defined as a named union, that's why we generate it as one

iscai-msft and others added 3 commits June 24, 2026 12:12
…ct copies from _models.py

- Only add 'from . import types' to sync __init__.py, not aio
  (types.py is generated at the sync level, aio doesn't have one)
- Filter out base='typeddict' models from _models.py class list
  (typeddict copies should only appear in types.py, not as model classes)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add 'List' import to ListType.imports() when property/operation named 'list'
  exists (fixes NameError in special-words types.py)
- Use has_non_json_models() for has_models in ModelInitSerializer to avoid
  generating 'from . import _models' when _models.py doesn't exist
- Remove 'from . import types' from __init__.py — each TypedDict type's
  imports() already handles adding the types import where needed (operations)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@iscai-msft iscai-msft force-pushed the python/addTypedDict branch from f77576c to 14b7d6c Compare June 24, 2026 20:20
iscai-msft and others added 2 commits June 24, 2026 16:31
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace is_operation_file with serialize_namespace_type to correctly
determine when to add the typing.List import. Operation/client files
only need it when has_operation_named_list is True, while model/types
files need it when has_property_named_list is True.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

[Python] Add alpha TypedDict support

5 participants