Skip to content

Commit 09e9b48

Browse files
authored
Add snippet updater to azpysdk (#45120)
* initial migrated script * minor * run black before update, refactor black * update pipeline step * add tests to azpysdk * minor * update doc * delete old script mentions * fail in update if black fails * minor fix * fix link * dont omit mgmt * fix, dont error if no samples dir * move test to proper location
1 parent 0d89e91 commit 09e9b48

12 files changed

Lines changed: 447 additions & 336 deletions

File tree

doc/dev/code_snippets.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ All code snippets in README should be up to date and runnable. And we want to ha
44

55
- [Define snippet definitions in the samples folder](#create-samples)
66
- [In README, refer to the code snippets from the samples](#refer-samples)
7-
- [Run `python_snippet_updater.py` to keep them in sync](#python_snippet_updater-tool)
7+
- [Run `azpysdk update_snippet .` from the package directory to keep them in sync](#run-update_snippet-tool)
88

99
## Create samples
1010

@@ -40,10 +40,13 @@ If you have a file in `samples\text_example_async.py` with a snippet named `asyn
4040

4141
> Make sure you include a Python code fence within the snippet reference!
4242
43-
## Run python_snippet_updater tool
43+
## Run update_snippet tool
44+
45+
The update_snippet tool is included in the [azpysdk CLI](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/tool_usage_guide.md), which is installed with `azure-sdk-tools`.
4446

4547
```powershell
46-
python <azure-sdk-for-python>/eng/tools/azure-sdk-tools/ci_tools/snippet_update/python_snippet_updater.py <path_to_the_service>
48+
cd <package_dir>
49+
azpysdk update_snippet .
4750
```
4851

4952
The script scans the snippets in samples folder and populates snippet references in README with the snippet definitions from samples folder.

doc/tool_usage_guide.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ The following checks are available via the `azpysdk` entrypoint.
3333
|`samples`| Runs the package's samples. | `azpysdk samples .` |
3434
|`optional`| Invokes 'optional' requirements for a given package. | `azpysdk optional .` |
3535
|`devtest`| Tests a package against dependencies installed from a dev index. | `azpysdk devtest .` |
36+
|`update_snippet`| Updates README code snippets from sample files. | `azpysdk update_snippet .` |
3637

3738
## Common arguments
3839

eng/pipelines/templates/steps/analyze.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ steps:
147147

148148
- template: /eng/pipelines/templates/steps/update_snippet.yml
149149
parameters:
150-
PackageInfoFolder: $(Build.ArtifactStagingDirectory)/PackageInfo
150+
ServiceDirectory: ${{ parameters.ServiceDirectory }}
151+
AdditionalTestArgs: ${{ parameters.AdditionalTestArgs }}
151152

152153
- template: ../steps/run_breaking_changes.yml
153154
parameters:
Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,18 @@
11
parameters:
2-
- name: PackageInfoFolder
3-
type: string
4-
default: ''
2+
ServiceDirectory: ''
3+
AdditionalTestArgs: ''
54

65
steps:
76
# this step should run on python 3.9.
87
# a previous step should have installed eng/ci_tools.txt to active venv
9-
- pwsh: |
10-
$failed = $false
11-
12-
if ("$(TargetingString)" -ne "null") {
13-
foreach($targetedPackage in "$(TargetingString)".split(',')) {
14-
$pkgInfo = Get-ChildItem -Path "${{ parameters.PackageInfoFolder }}" -Recurse -Filter "$targetedPackage.json" `
15-
| Get-Content -Raw `
16-
| ConvertFrom-Json
17-
18-
if ($pkgInfo) {
19-
python eng/tools/azure-sdk-tools/ci_tools/snippet_update/python_snippet_updater.py "$(Build.SourcesDirectory)/sdk/$($pkgInfo.ServiceDirectory)/$targetedPackage"
20-
}
21-
else {
22-
Write-Error "Unable to obtain package info for $targetedPackage."
23-
$failed = $true
24-
}
25-
26-
if ($LASTEXITCODE -ne 0) {
27-
Write-Error "Failed to update snippets for $targetedPackage."
28-
$failed = $true
29-
}
30-
}
31-
32-
if ($failed) {
33-
Write-Error "At least one snippet update failed. Check above output for details."
34-
exit 1
35-
}
36-
}
37-
displayName: Update Snippets
8+
- task: PythonScript@0
9+
displayName: 'Update Snippets'
10+
inputs:
11+
scriptPath: 'eng/scripts/dispatch_checks.py'
12+
arguments: >-
13+
"$(TargetingString)"
14+
--service="${{ parameters.ServiceDirectory }}"
15+
--checks="update_snippet"
16+
--disable-compatibility-filter
17+
${{ parameters.AdditionalTestArgs }}
3818
condition: and(succeededOrFailed(), ne(variables['Skip.UpdateSnippet'],'true'))

eng/tools/azure-sdk-tools/azpysdk/black.py

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -50,50 +50,55 @@ def run(self, args: argparse.Namespace) -> int:
5050

5151
self.install_dev_reqs(executable, args, package_dir)
5252

53-
# install black
54-
try:
55-
install_into_venv(executable, [f"black=={BLACK_VERSION}"], package_dir)
56-
except CalledProcessError as e:
57-
logger.error(f"Failed to install black: {e}")
58-
return e.returncode
59-
6053
logger.info(f"Running black against {package_name}")
6154

62-
config_file_location = os.path.join(REPO_ROOT, "eng/black-pyproject.toml")
63-
6455
if in_ci():
6556
if not is_check_enabled(package_dir, "black", default=False):
6657
logger.info(f"Package {package_name} opts-out of black check.")
6758
continue
68-
try:
69-
run_result = subprocess.run(
70-
[
71-
executable,
72-
"-m",
73-
"black",
74-
f"--config={config_file_location}",
75-
package_dir,
76-
],
77-
stdout=subprocess.PIPE,
78-
stderr=subprocess.PIPE,
79-
check=True,
80-
)
81-
82-
if run_result.stderr and "reformatted" in run_result.stderr.decode("utf-8"):
83-
if in_ci():
84-
logger.info(
85-
f"The package {package_name} needs reformat. Run `azpysdk black .` locally from the package root to reformat."
86-
)
87-
results.append(1)
88-
else:
89-
logger.info(f"The package {package_name} was reformatted.")
90-
else:
91-
logger.info(f"The package {package_name} is properly formatted, no files changed.")
9259

93-
except subprocess.CalledProcessError as e:
94-
logger.error(f"Unable to invoke black for {package_name}. Ran into exception {e}.")
95-
if e.stderr:
96-
logger.error(e.stderr.decode("utf-8"))
97-
results.append(e.returncode)
60+
result = self.format_directory(executable, package_dir)
61+
if result is None:
62+
# install or formatting failed, already logged
63+
results.append(1)
64+
continue
65+
66+
if result.stderr and "reformatted" in result.stderr.decode("utf-8"):
67+
if in_ci():
68+
logger.info(
69+
f"The package {package_name} needs reformat. Run `azpysdk black .` locally from the package root to reformat."
70+
)
71+
results.append(1)
72+
else:
73+
logger.info(f"The package {package_name} was reformatted.")
74+
else:
75+
logger.info(f"The package {package_name} is properly formatted, no files changed.")
9876

9977
return max(results) if results else 0
78+
79+
@staticmethod
80+
def format_directory(executable: str, target_dir: str) -> Optional[subprocess.CompletedProcess]:
81+
"""Run black on *target_dir* using the repo-wide config.
82+
83+
Installs the pinned black version into the environment of *executable*,
84+
then formats all Python files under *target_dir*.
85+
"""
86+
try:
87+
install_into_venv(executable, [f"black=={BLACK_VERSION}"], target_dir)
88+
except CalledProcessError as e:
89+
logger.error(f"Failed to install black, skipping formatting: {e}")
90+
return None
91+
92+
config_file_location = os.path.join(REPO_ROOT, "eng/black-pyproject.toml")
93+
try:
94+
return subprocess.run(
95+
[executable, "-m", "black", f"--config={config_file_location}", target_dir],
96+
stdout=subprocess.PIPE,
97+
stderr=subprocess.PIPE,
98+
check=True,
99+
)
100+
except subprocess.CalledProcessError as e:
101+
logger.error(f"Black formatting failed for {target_dir}: {e}")
102+
if e.stderr:
103+
logger.error(e.stderr.decode("utf-8"))
104+
return None

eng/tools/azure-sdk-tools/azpysdk/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
from .samples import samples
4141
from .devtest import devtest
4242
from .optional import optional
43+
from .update_snippet import update_snippet
4344

4445
from ci_tools.logging import configure_logging, logger
4546

@@ -115,6 +116,7 @@ def build_parser() -> argparse.ArgumentParser:
115116
samples().register(subparsers, [common])
116117
devtest().register(subparsers, [common])
117118
optional().register(subparsers, [common])
119+
update_snippet().register(subparsers, [common])
118120

119121
return parser
120122

0 commit comments

Comments
 (0)