Regenerate the local emitter and diff the generated code against the upstream baseline checked into autorest.python. Use this skill when the user wants to see how their emitter changes affect generated code compared to what's currently in production, says things like "diff upstream", "compare to baseline", "what changed vs production", "show me the diff", "how does this affect generated code", or wants to validate their changes produce the expected output differences.
Regenerates local emitter output and compares it against the baseline generated code checked into the autorest.python repository. Shows exactly what would change if the current emitter changes were shipped.
Optimized for local development with cached baseline and editor integration.
All paths are relative to the http-client-python package root.
| Item | Path |
|---|---|
| Package root | ~/Desktop/github/typespec/packages/http-client-python |
| Local generated (unbranded) | generator/test/unbranded/generated |
| Local generated (azure) | generator/test/azure/generated |
| Baseline cache (unbranded) | generator/test/unbranded/.baseline (gitignored) |
| Baseline cache (azure) | generator/test/azure/.baseline (gitignored) |
| Diff summary output | generator/test/.diff-summary.md (gitignored) |
| Regenerate marker |
.last-regenerate |
| Upstream repo | https://github.com/Azure/autorest.python |
Always regenerate to see current changes:
cd ~/Desktop/github/typespec/packages/http-client-python
npm run build
npm run regenerate
touch .last-regenerate
If build or regenerate fails, report errors and stop.
Fetch baseline files directly into the test folders using sparse checkout:
cd ~/Desktop/github/typespec/packages/http-client-python
BASELINE_UNBRANDED="generator/test/unbranded/.baseline"
BASELINE_AZURE="generator/test/azure/.baseline"
TEMP_CLONE="/tmp/autorest-python-baseline-$$"
# Check if we need to fetch/update
if [ ! -d "$BASELINE_UNBRANDED" ] || [ ! -d "$BASELINE_AZURE" ]; then
echo "Fetching upstream baseline..."
# Clone with sparse checkout to temp location
git clone --depth 1 --filter=blob:none --sparse \
https://github.com/Azure/autorest.python.git "$TEMP_CLONE"
cd "$TEMP_CLONE"
git sparse-checkout set \
packages/typespec-python/test/unbranded/generated \
packages/typespec-python/test/azure/generated
cd ~/Desktop/github/typespec/packages/http-client-python
# Copy to baseline locations
rm -rf "$BASELINE_UNBRANDED" "$BASELINE_AZURE"
cp -r "$TEMP_CLONE/packages/typespec-python/test/unbranded/generated" "$BASELINE_UNBRANDED"
cp -r "$TEMP_CLONE/packages/typespec-python/test/azure/generated" "$BASELINE_AZURE"
# Cleanup temp clone
rm -rf "$TEMP_CLONE"
echo "Baseline cached in generator/test/*/.baseline/"
else
echo "Using cached baseline (delete generator/test/*/.baseline to refresh)"
fi
Create a markdown summary file with package-level comparison:
cd ~/Desktop/github/typespec/packages/http-client-python
LOCAL_UNBRANDED="generator/test/unbranded/generated"
LOCAL_AZURE="generator/test/azure/generated"
BASELINE_UNBRANDED="generator/test/unbranded/.baseline"
BASELINE_AZURE="generator/test/azure/.baseline"
cat > generator/test/.diff-summary.md << EOF
# Diff Summary: Local vs Upstream (autorest.python)
Generated: $(date)
## Unbranded Packages
| Metric | Count |
|--------|-------|
| Local | $(ls "$LOCAL_UNBRANDED" 2> /dev/null | wc -l | tr -d ' ') |
| Upstream | $(ls "$BASELINE_UNBRANDED" 2> /dev/null | wc -l | tr -d ' ') |
### Missing locally (in upstream only):
$(comm -13 <(ls "$LOCAL_UNBRANDED" 2> /dev/null | sort) <(ls "$BASELINE_UNBRANDED" 2> /dev/null | sort) | sed 's/^/- /' || echo "- (none)")
### New locally (not in upstream):
$(comm -23 <(ls "$LOCAL_UNBRANDED" 2> /dev/null | sort) <(ls "$BASELINE_UNBRANDED" 2> /dev/null | sort) | sed 's/^/- /' || echo "- (none)")
## Azure Packages
| Metric | Count |
|--------|-------|
| Local | $(ls "$LOCAL_AZURE" 2> /dev/null | wc -l | tr -d ' ') |
| Upstream | $(ls "$BASELINE_AZURE" 2> /dev/null | wc -l | tr -d ' ') |
### Missing locally (in upstream only):
$(comm -13 <(ls "$LOCAL_AZURE" 2> /dev/null | sort) <(ls "$BASELINE_AZURE" 2> /dev/null | sort) | sed 's/^/- /' || echo "- (none)")
### New locally (not in upstream):
$(comm -23 <(ls "$LOCAL_AZURE" 2> /dev/null | sort) <(ls "$BASELINE_AZURE" 2> /dev/null | sort) | sed 's/^/- /' || echo "- (none)")
---
## Viewing Detailed Diffs
### List changed files in a package:
\`\`\`bash
diff -rq generator/test/unbranded/generated/PACKAGE generator/test/unbranded/.baseline/PACKAGE
\`\`\`
### View full diff for a package:
\`\`\`bash
diff -r generator/test/unbranded/generated/PACKAGE generator/test/unbranded/.baseline/PACKAGE
\`\`\`
### Open side-by-side diff in VS Code:
\`\`\`bash
code --diff generator/test/unbranded/.baseline/PACKAGE/path/to/file.py generator/test/unbranded/generated/PACKAGE/path/to/file.py
\`\`\`
EOF
Open the summary file in the user's preferred editor:
cd ~/Desktop/github/typespec/packages/http-client-python
# Try common editors in order of preference
if command -v code &> /dev/null; then
code generator/test/.diff-summary.md
elif [ -n "$VISUAL" ]; then
$VISUAL generator/test/.diff-summary.md
elif [ -n "$EDITOR" ]; then
$EDITOR generator/test/.diff-summary.md
elif command -v vim &> /dev/null; then
vim generator/test/.diff-summary.md
else
cat generator/test/.diff-summary.md
fi
Tell the user:
generator/test/.diff-summary.mdgenerator/test/*/.baseline/rm -rf generator/test/*/.baselineAfter showing the summary, if the user wants to see specific file changes:
cd ~/Desktop/github/typespec/packages/http-client-python
diff -rq \
generator/test/unbranded/generated/typetest-array \
generator/test/unbranded/.baseline/typetest-array
diff -u \
generator/test/unbranded/.baseline/typetest-array/typetest/array/_client.py \
generator/test/unbranded/generated/typetest-array/typetest/array/_client.py
code --diff \
generator/test/unbranded/.baseline/typetest-array/typetest/array/_client.py \
generator/test/unbranded/generated/typetest-array/typetest/array/_client.py
After running diff-upstream, you can immediately run tests:
.last-regenerate marker is updatedtest-unbranded-emitter will skip regeneration since it's freshThe baseline is cached for fast subsequent runs. To refresh:
# Remove baseline (will re-fetch on next run)
rm -rf generator/test/unbranded/.baseline generator/test/azure/.baseline
# Remove summary file
rm generator/test/.diff-summary.md
These patterns should be in .gitignore:
generator/test/unbranded/.baseline/
generator/test/azure/.baseline/
generator/test/.diff-summary.md
.last-regenerate
After generating the diff, analyze what changed and report to the user whether the diffs are expected.
First, understand what emitter changes were made:
# Show commits on this branch
git log main..HEAD --oneline -- "emitter/src/*.ts"
# Show the actual changes
git diff main..HEAD -- emitter/src/
Based on the emitter changes, determine what generated code SHOULD change:
| Emitter change type | Expected generated code impact |
|---|---|
| Namespace logic refactor (behavior-preserving) | No generated code changes |
| New decorator support | Changes in files using that decorator |
| Serialization changes | Changes in _serialization.py, model files |
| Client initialization changes | Changes in _client.py, _configuration.py |
| Operation changes | Changes in _operations/*.py |
If actual diffs match expected: Tell user "The diffs are expected based on your emitter changes to [describe changes]. The generated code correctly reflects your modifications."
If no diffs but expected some: Tell user "No generated code changes detected. If you expected changes, verify your emitter modifications are being triggered by the test specs, or there may be more development needed. Should I investigate further?"
If unexpected diffs appear: Tell user "Found unexpected changes in [files]. These don't appear to match your emitter modifications. There may be unintended side effects - would you like me to investigate?"
These diffs exist between typespec and autorest.python repos regardless of emitter changes. They should be ignored when evaluating your changes:
| File type | Typical diff | Cause |
|---|---|---|
_patch.py | List[str] → list[str] | Type hint modernization (Python 3.9+ style) |
CHANGELOG.md | Formatting differences | Template differences |
README.md | Service display names | Template/config differences |
pyproject.toml / setup.py | Different packaging | Tooling preferences |
If only these files differ: "The only diffs are pre-existing repo differences (type hints, config files), not caused by your emitter changes. Your changes are behavior-preserving."
If you see differences in these files, the emitter changes ARE affecting generated code:
_client.py - Client class definitions_operations/*.py - Operation implementationsmodels/*.py - Model definitions (excluding _patch.py)_serialization.py - Serialization logicaio/*.py - Async client codeIf these files differ: First check if the changes match what the emitter modifications should produce. If they match, say "The generated code changes are expected based on your emitter changes." If they don't match or are unexpected, say "Found changes that don't appear to match your emitter modifications. There may be more development needed - would you like me to investigate?"
To check if there are actual code changes (excluding expected differences):
diff -rq generator/test/unbranded/generated generator/test/unbranded/.baseline 2> /dev/null | grep "\.py differ" | grep -v "_patch.py"
If this returns nothing, only expected diffs exist.
The diff shows changes from upstream (baseline) to local (your changes):
- lines: removed from upstream (or changed)+ lines: added in your local versionSome upstream packages may not generate locally due to:
This is expected for ARM/azure-resource-manager specs if there are version conflicts.