Skip to content

Fix Python ETag preprocessing for nested operation groups - #11964

Open
Libba Lawrence (l0lawrence) wants to merge 7 commits into
mainfrom
llawrence/fix-required-etag-headers
Open

Libba Lawrence (l0lawrence) wants to merge 7 commits into
mainfrom
llawrence/fix-required-etag-headers

Conversation

@l0lawrence

@l0lawrence Libba Lawrence (l0lawrence) commented Sep 14, 2026

Copy link
Copy Markdown
Member

Summary

  • recursively preprocess ETag headers in nested operation groups while retaining the owning root client
  • synthesize the existing match_condition partner without inferring a default, leaving required etag and match_condition parameters required
  • preserve the original immediate-group scope for unrelated client-request-id detection
  • add a nested preprocessing regression that verifies helper-generation state and required parameters

Root cause

The emitter correctly assigns etagRole to conditional headers. Python preprocessing then handled ETag setup only for immediate operation groups, while the later parameter transformation already recursed into descendants. Nested operations were therefore partially transformed: ifMatch became etag, but no match_condition partner was synthesized and neither the operation nor root client enabled ETag helper imports.

Required-header API

A required If-Match: Azure.Core.eTag in a nested operation group now generates the existing Python convenience API coherently:

def remove(
    self,
    *,
    etag: str,
    match_condition: MatchConditions,
    **kwargs: Any,
) -> None:

Both values are required and forwarded to prep_if_match; no match condition is inferred by the generator. The service remains responsible for validating the resulting conditional request.

Validation

  • focused ETag preprocessing suite: 9 passed
  • package formatting check passed
  • package lint passed
  • minimal nested TypeSpec reproduction generated coherent sync and async clients
  • generated sync/async Python byte-compilation passed

No Spector scenario changes are included.

Co-authored-by: Copilot App <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 Sep 14, 2026
@pkg-pr-new

pkg-pr-new Bot commented Sep 14, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 96d6bab

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/http-client-python
Show changes

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

Generate complete ETag handling for operations in nested operation groups.

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Python emitter diff

Baseline gh:057557b68f845fc64f4ed7cbca15affe0414825a 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.

@azure-sdk-automation

azure-sdk-automation Bot commented Sep 14, 2026

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@l0lawrence Libba Lawrence (l0lawrence) changed the title Fix required eTag conditional headers in Python Fix Python ETag preprocessing for nested operation groups Sep 15, 2026
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread packages/http-client-python/generator/pygen/preprocess/__init__.py Outdated

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

Add regression assertions covering optional lone and both-role ETag paths.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Fixes Python ETag preprocessing for nested operation groups and required conditional headers.

Changes:

  • Recursively processes nested ETag headers while retaining root-client state.
  • Adds defaults for lone required If-Match and If-None-Match headers.
  • Adds regression tests and a Chronus changelog entry.
File summaries
File Description
packages/http-client-python/tests/unit/test_preprocess_etag.py Adds nested and edge-case regression tests.
packages/http-client-python/generator/pygen/preprocess/__init__.py Implements recursive ETag handling and conditional defaults.
.chronus/changes/fix-required-etag-header-2026-09-14.md Records the Python emitter fix.
Review details

Suppressed comments (1)

packages/http-client-python/tests/unit/test_preprocess_etag.py:350

  • The new negative test covers only the multiple-candidate case. The optional guard in lines 275-278 is the other advertised non-default path, but no test asserts that a lone optional header's synthesized partner lacks clientDefaultValue; add a regression case here so that guard cannot be removed without failing the suite.
def test_required_match_condition_default_not_added_for_multiple_candidates():
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/http-client-python/generator/pygen/preprocess/__init__.py Outdated

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.

🔵 Needs a closer look

Add regression coverage for immediate versus nested client-request-id handling.

Review details

Suppressed comments (1)

packages/http-client-python/generator/pygen/preprocess/init.py:625

  • This new requestIdHeaderName loop has no regression coverage for the explicitly preserved immediate-group scope: the added test only exercises nested ETag processing. Please add cases proving an immediate operation still sets requestIdHeaderName while the same header in a nested group does not, so this behavior cannot silently change during the recursion refactor.
        for operation_group in yaml_data.get("operationGroups", []):
            for operation in operation_group.get("operations", []):
                for parameter in operation["parameters"]:
                    if parameter["location"] == "header" and get_wire_name_lower(parameter) == "client-request-id":
                        yaml_data["requestIdHeaderName"] = "client-request-id"
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

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