From 8ed9269b9ed0fd215dbb523d1e3ba8f679cff2b2 Mon Sep 17 00:00:00 2001 From: jennypng <63012604+JennyPng@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:27:37 -0800 Subject: [PATCH 1/7] cut --- eng/pipelines/templates/steps/run_apistub.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/eng/pipelines/templates/steps/run_apistub.yml b/eng/pipelines/templates/steps/run_apistub.yml index ea84514f3ba0..cf738f19a922 100644 --- a/eng/pipelines/templates/steps/run_apistub.yml +++ b/eng/pipelines/templates/steps/run_apistub.yml @@ -31,14 +31,18 @@ steps: condition: and(succeededOrFailed(), ne(variables['Skip.ApiStubGen'],'true')) displayName: 'Generate API stub files' inputs: - scriptPath: 'scripts/devops_tasks/dispatch_tox.py' + scriptPath: 'eng/scripts/dispatch_checks.py' arguments: >- "$(TargetingString)" ${{ parameters.AdditionalTestArgs }} -d "$(Build.ArtifactStagingDirectory)" --mark_arg="${{ parameters.TestMarkArgument }}" --service="${{ parameters.ServiceDirectory }}" - --toxenv="apistub" + --checks="apistub" --disablecov --filter-type="Omit_management" - ${{ parameters.AdditionalTestArgs }} \ No newline at end of file + ${{ parameters.AdditionalTestArgs }} + env: + TOX_PIP_IMPL: "uv" + VIRTUAL_ENV: "" + PYTHONHOME: "" \ No newline at end of file From 7bd578519dddbd275f6dc8dbff0211e7099356a5 Mon Sep 17 00:00:00 2001 From: jennypng <63012604+JennyPng@users.noreply.github.com> Date: Tue, 16 Dec 2025 12:56:57 -0800 Subject: [PATCH 2/7] ensurepip --- eng/tools/azure-sdk-tools/azpysdk/Check.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/eng/tools/azure-sdk-tools/azpysdk/Check.py b/eng/tools/azure-sdk-tools/azpysdk/Check.py index 212e089b82d0..049e943d38a4 100644 --- a/eng/tools/azure-sdk-tools/azpysdk/Check.py +++ b/eng/tools/azure-sdk-tools/azpysdk/Check.py @@ -71,6 +71,10 @@ def create_venv(self, isolate: bool, venv_location: str) -> str: subprocess.check_call(venv_cmd + [venv_location]) + # ensure uv venv has pip for tools that require pip + if venv_cmd[0] == "uv": + subprocess.check_call([venv_python, "-m", "ensurepip", "--upgrade"]) + if in_ci(): # first attempt to retrieve azure-sdk-tools from the prebuilt wheel directory # if present, install from there instead of constantly rebuilding azure-sdk-tools in a possible From 21bd4ba0e1764d3d2eaa35d0af985e4425c0d631 Mon Sep 17 00:00:00 2001 From: jennypng <63012604+JennyPng@users.noreply.github.com> Date: Tue, 16 Dec 2025 13:02:45 -0800 Subject: [PATCH 3/7] try except --- eng/tools/azure-sdk-tools/azpysdk/Check.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/eng/tools/azure-sdk-tools/azpysdk/Check.py b/eng/tools/azure-sdk-tools/azpysdk/Check.py index 049e943d38a4..e4a3b30f6ed6 100644 --- a/eng/tools/azure-sdk-tools/azpysdk/Check.py +++ b/eng/tools/azure-sdk-tools/azpysdk/Check.py @@ -73,7 +73,10 @@ def create_venv(self, isolate: bool, venv_location: str) -> str: # ensure uv venv has pip for tools that require pip if venv_cmd[0] == "uv": - subprocess.check_call([venv_python, "-m", "ensurepip", "--upgrade"]) + try: + subprocess.check_call([venv_python, "-m", "ensurepip", "--upgrade"]) + except subprocess.CalledProcessError as e: + logger.error(f"Failed to ensure pip in uv venv: {e}") if in_ci(): # first attempt to retrieve azure-sdk-tools from the prebuilt wheel directory From 538cff788136c87cbb14539c5f80702dc97cde2c Mon Sep 17 00:00:00 2001 From: jennypng <63012604+JennyPng@users.noreply.github.com> Date: Tue, 16 Dec 2025 13:29:57 -0800 Subject: [PATCH 4/7] fixes --- eng/tools/azure-sdk-tools/azpysdk/Check.py | 2 +- eng/tools/azure-sdk-tools/azpysdk/apistub.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/tools/azure-sdk-tools/azpysdk/Check.py b/eng/tools/azure-sdk-tools/azpysdk/Check.py index e4a3b30f6ed6..697a32ce4525 100644 --- a/eng/tools/azure-sdk-tools/azpysdk/Check.py +++ b/eng/tools/azure-sdk-tools/azpysdk/Check.py @@ -74,7 +74,7 @@ def create_venv(self, isolate: bool, venv_location: str) -> str: # ensure uv venv has pip for tools that require pip if venv_cmd[0] == "uv": try: - subprocess.check_call([venv_python, "-m", "ensurepip", "--upgrade"]) + subprocess.check_call(["uv", "pip", "install", "--python", venv_python, "pip"]) except subprocess.CalledProcessError as e: logger.error(f"Failed to ensure pip in uv venv: {e}") diff --git a/eng/tools/azure-sdk-tools/azpysdk/apistub.py b/eng/tools/azure-sdk-tools/azpysdk/apistub.py index 183f76aee7ae..2fb7c252edeb 100644 --- a/eng/tools/azure-sdk-tools/azpysdk/apistub.py +++ b/eng/tools/azure-sdk-tools/azpysdk/apistub.py @@ -34,7 +34,7 @@ def get_package_wheel_path(pkg_root: str, out_path: Optional[str]) -> tuple[str, ) # If the package is a wheel and out_path is given, the token file output path should be the parent directory of the wheel if out_path: - out_token_path = os.path.join(out_path, os.path.basename(os.path.dirname(pkg_path))) + out_token_path = out_path return pkg_path, out_token_path # Otherwise, use wheel created in staging directory, or fall back on source directory From 8397d46d980e9b083ee057f3bb9c724c9424e906 Mon Sep 17 00:00:00 2001 From: jennypng <63012604+JennyPng@users.noreply.github.com> Date: Fri, 19 Dec 2025 11:21:29 -0800 Subject: [PATCH 5/7] fix ...namespace collision..? --- eng/tools/azure-sdk-tools/azpysdk/apistub.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/eng/tools/azure-sdk-tools/azpysdk/apistub.py b/eng/tools/azure-sdk-tools/azpysdk/apistub.py index 2fb7c252edeb..d2da18f591fb 100644 --- a/eng/tools/azure-sdk-tools/azpysdk/apistub.py +++ b/eng/tools/azure-sdk-tools/azpysdk/apistub.py @@ -106,7 +106,7 @@ def run(self, args: argparse.Namespace) -> int: create_package_and_install( distribution_directory=staging_directory, target_setup=package_dir, - skip_install=True, + skip_install=False, cache_dir=None, work_dir=staging_directory, force_create=False, @@ -120,6 +120,12 @@ def run(self, args: argparse.Namespace) -> int: pkg_path, out_token_path = get_package_wheel_path(package_dir, staging_directory) cross_language_mapping_path = get_cross_language_mapping_path(package_dir) + pkg_path = os.path.abspath(pkg_path) + if out_token_path: + out_token_path = os.path.abspath(out_token_path) + if cross_language_mapping_path: + cross_language_mapping_path = os.path.abspath(cross_language_mapping_path) + cmds = ["-m", "apistub", "--pkg-path", pkg_path] if out_token_path: @@ -130,7 +136,9 @@ def run(self, args: argparse.Namespace) -> int: logger.info("Running apistub {}.".format(cmds)) try: - self.run_venv_command(executable, cmds, cwd=package_dir, check=True, immediately_dump=True) + # Run from staging directory instead of package_dir to avoid namespace collisions + # when the package has namespace packages (e.g., azure.core.experimental) + self.run_venv_command(executable, cmds, cwd=staging_directory, check=True, immediately_dump=True) except CalledProcessError as e: logger.error(f"{package_name} exited with error {e.returncode}") results.append(e.returncode) From bececd9b8160117ba65e10169c4da5c965cee3ca Mon Sep 17 00:00:00 2001 From: jennypng <63012604+JennyPng@users.noreply.github.com> Date: Fri, 19 Dec 2025 11:30:56 -0800 Subject: [PATCH 6/7] clean --- eng/tools/azure-sdk-tools/azpysdk/apistub.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/eng/tools/azure-sdk-tools/azpysdk/apistub.py b/eng/tools/azure-sdk-tools/azpysdk/apistub.py index d2da18f591fb..9a577d8fcc8a 100644 --- a/eng/tools/azure-sdk-tools/azpysdk/apistub.py +++ b/eng/tools/azure-sdk-tools/azpysdk/apistub.py @@ -136,8 +136,6 @@ def run(self, args: argparse.Namespace) -> int: logger.info("Running apistub {}.".format(cmds)) try: - # Run from staging directory instead of package_dir to avoid namespace collisions - # when the package has namespace packages (e.g., azure.core.experimental) self.run_venv_command(executable, cmds, cwd=staging_directory, check=True, immediately_dump=True) except CalledProcessError as e: logger.error(f"{package_name} exited with error {e.returncode}") From fadc5ab8e896f0c6b16024099f1102f6e30e9a95 Mon Sep 17 00:00:00 2001 From: jennypng <63012604+JennyPng@users.noreply.github.com> Date: Fri, 19 Dec 2025 11:53:16 -0800 Subject: [PATCH 7/7] remove unused param --- eng/tools/azure-sdk-tools/azpysdk/apistub.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/eng/tools/azure-sdk-tools/azpysdk/apistub.py b/eng/tools/azure-sdk-tools/azpysdk/apistub.py index 9a577d8fcc8a..d97d68edc4bb 100644 --- a/eng/tools/azure-sdk-tools/azpysdk/apistub.py +++ b/eng/tools/azure-sdk-tools/azpysdk/apistub.py @@ -16,13 +16,12 @@ MAX_PYTHON_VERSION = (3, 11) -def get_package_wheel_path(pkg_root: str, out_path: Optional[str]) -> tuple[str, Optional[str]]: +def get_package_wheel_path(pkg_root: str) -> str: # parse setup.py to get package name and version pkg_details = ParsedSetup.from_path(pkg_root) # Check if wheel is already built and available for current package prebuilt_dir = os.getenv("PREBUILT_WHEEL_DIR") - out_token_path = None if prebuilt_dir: found_whl = find_whl(prebuilt_dir, pkg_details.name, pkg_details.version) pkg_path = os.path.join(prebuilt_dir, found_whl) if found_whl else None @@ -32,16 +31,10 @@ def get_package_wheel_path(pkg_root: str, out_path: Optional[str]) -> tuple[str, pkg_details.name, pkg_details.version, prebuilt_dir ) ) - # If the package is a wheel and out_path is given, the token file output path should be the parent directory of the wheel - if out_path: - out_token_path = out_path - return pkg_path, out_token_path - + return pkg_path # Otherwise, use wheel created in staging directory, or fall back on source directory pkg_path = find_whl(pkg_root, pkg_details.name, pkg_details.version) or pkg_root - out_token_path = out_path - - return pkg_path, out_token_path + return pkg_path def get_cross_language_mapping_path(pkg_root): @@ -117,7 +110,8 @@ def run(self, args: argparse.Namespace) -> int: self.pip_freeze(executable) - pkg_path, out_token_path = get_package_wheel_path(package_dir, staging_directory) + pkg_path = get_package_wheel_path(package_dir) + out_token_path = staging_directory cross_language_mapping_path = get_cross_language_mapping_path(package_dir) pkg_path = os.path.abspath(pkg_path)