Repository navigation
Python: Preserve substituted values in declarative templates - #9096
Merged
Eduard van Valkenburg (eavanvalkenburg) merged 1 commit intoOct 13, 2026
Conversation
LI (ktz03)
temporarily deployed
to
github-app-auth
October 5, 2026 23:48 — with
GitHub Actions
Inactive
LI (ktz03)
temporarily deployed
to
github-app-auth
October 5, 2026 23:48 — with
GitHub Actions
Inactive
Contributor
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused implementation preserves existing behavior while comprehensively testing the reported edge cases.
Review effort: Balanced
Findings: None
What changed in this PR
Fixes declarative template interpolation so substitutions apply only to authored placeholders.
Changes:
- Uses a regex callback over the original template.
- Documents literal substituted values.
- Adds regression coverage for string/mapping and streaming workflows.
| File | Description |
|---|---|
_declarative_base.py |
Corrects interpolation behavior. |
test_graph_executors.py |
Adds comprehensive regression tests. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
LI (ktz03)
marked this pull request as ready for review
October 12, 2026 10:15
LI (ktz03)
temporarily deployed
to
github-app-auth
October 12, 2026 10:16 — with
GitHub Actions
Inactive
Eduard van Valkenburg (eavanvalkenburg)
approved these changes
Oct 13, 2026
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation & Context
A
SendActivitytemplate can rewrite substituted values and leave authored placeholders unresolved. WithLocal.first = "{Local.second}"andLocal.second = "B",{Local.first}|{Local.second}currently producesB|{Local.second}instead of{Local.second}|B. Each replacement searches an already-modified string, so it can consume text inserted by an earlier substitution.Description & Review Guide
What are the major changes?
Replace the sequential string-replacement loop with a regex callback over the original template. Keep the existing matcher, state-path resolution, string conversion, and missing-value behavior. Document that substituted values remain literal.
What is the impact of these changes?
Only authored template occurrences are substituted. Repeated and overlapping placeholder values, including references inside lists or dictionaries, remain intact. Thirty-two regression tests cover string and mapping activities, with both ordinary and streaming execution in each test. They change from twelve failures and twenty passing controls to thirty-two passing tests. The complete declarative package suite passes 1,379 tests with no skips and 93% coverage on Windows/Python 3.12.14. Formatting/lint, strict source Pyright, all five test type checkers, applicable prek hooks, and wheel/sdist builds pass. No external service, model, other platform, or performance test was run.
What do you want reviewers to focus on?
Preservation of original template positions and literal substituted values, including backslashes, while retaining ordinary interpolation and guarded state-path lookup. Expression evaluation and the expression-result behavior from Python: [BREAKING] preserve expression results in SendActivity output #8509 are unchanged.
Related Issue
Fixes #9095
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.