From dadd9d636cb210dea093ef1da9e1647d88b31605 Mon Sep 17 00:00:00 2001 From: Laurent Mazuel Date: Thu, 21 Aug 2025 15:19:11 -0700 Subject: [PATCH 1/4] Add option to run uv easily if wanted --- .gitignore | 3 + eng/tools/azure-sdk-tools/azpysdk/__init__.py | 0 eng/tools/azure-sdk-tools/azpysdk/main.py | 93 +++++++++++++++++++ eng/tools/azure-sdk-tools/pyproject.toml | 64 +++++++++++++ eng/tools/azure-sdk-tools/setup.py | 64 ------------- .../azure-keyvault-keys/pyproject.toml | 17 ++++ 6 files changed, 177 insertions(+), 64 deletions(-) create mode 100644 eng/tools/azure-sdk-tools/azpysdk/__init__.py create mode 100644 eng/tools/azure-sdk-tools/azpysdk/main.py delete mode 100644 eng/tools/azure-sdk-tools/setup.py diff --git a/.gitignore b/.gitignore index 0e05986885a9..23a9c757ffda 100644 --- a/.gitignore +++ b/.gitignore @@ -172,3 +172,6 @@ component-detection-pip-report.json **/.pydevproject **/.settings .github/prompts/copilot-instructions.md + +# No uv lock for now +uv.lock \ No newline at end of file diff --git a/eng/tools/azure-sdk-tools/azpysdk/__init__.py b/eng/tools/azure-sdk-tools/azpysdk/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/eng/tools/azure-sdk-tools/azpysdk/main.py b/eng/tools/azure-sdk-tools/azpysdk/main.py new file mode 100644 index 000000000000..e834b4f335f4 --- /dev/null +++ b/eng/tools/azure-sdk-tools/azpysdk/main.py @@ -0,0 +1,93 @@ +"""azpysdk CLI + +A minimal command-line interface using argparse. This file provides a +`main()` entrypoint so the package can be invoked as a module +(e.g. `python -m azpysdk.main`) or installed as a console script. +""" + +from __future__ import annotations + +import argparse +import sys +from typing import Sequence, Optional + +__all__ = ["main", "build_parser"] +__version__ = "0.0.0" + + +def _cmd_greet(args: argparse.Namespace) -> int: + """Simple greet command: prints a greeting.""" + name = args.name or "world" + print(f"Hello, {name}!") + return 0 + + +def _cmd_echo(args: argparse.Namespace) -> int: + """Echo command: prints back the provided message.""" + print(args.message) + return 0 + + +def _cmd_run(args: argparse.Namespace) -> int: + """Run command: placeholder for running a task or pipeline.""" + print(f"Running task: {args.task}") + # TODO: implement real behaviour + return 0 + + +def build_parser() -> argparse.ArgumentParser: + """Create and return the top-level ArgumentParser for the CLI.""" + parser = argparse.ArgumentParser( + prog="azpysdk", description="Azure SDK Python tools (minimal CLI)" + ) + parser.add_argument("-V", "--version", action="version", version=__version__) + + subparsers = parser.add_subparsers(title="commands", dest="command") + + # greet + p = subparsers.add_parser("greet", help="Greet someone") + p.add_argument("-n", "--name", help="Name to greet") + p.set_defaults(func=_cmd_greet) + + # echo + p = subparsers.add_parser("echo", help="Echo a message") + p.add_argument("message", help="Message to echo") + p.set_defaults(func=_cmd_echo) + + # run + p = subparsers.add_parser("run", help="Run a placeholder task") + p.add_argument("-t", "--task", default="default", help="Task name to run") + p.set_defaults(func=_cmd_run) + + return parser + + +def main(argv: Optional[Sequence[str]] = None) -> int: + """CLI entrypoint. + + Args: + argv: Optional list of arguments to parse (defaults to sys.argv[1:]). + + Returns: + Exit code to return to the OS. + """ + parser = build_parser() + args = parser.parse_args(argv) + + if not hasattr(args, "func"): + parser.print_help() + return 1 + + try: + result = args.func(args) + return int(result or 0) + except KeyboardInterrupt: + print("Interrupted by user", file=sys.stderr) + return 130 + except Exception as exc: # pragma: no cover - simple top-level error handling + print(f"Error: {exc}", file=sys.stderr) + return 2 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/eng/tools/azure-sdk-tools/pyproject.toml b/eng/tools/azure-sdk-tools/pyproject.toml index 56c3ff3bf7f1..fcb4bccc9ad2 100644 --- a/eng/tools/azure-sdk-tools/pyproject.toml +++ b/eng/tools/azure-sdk-tools/pyproject.toml @@ -1,3 +1,67 @@ +[build-system] +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "azure-sdk-tools" +version = "0.0.0" +description = "Build and test tooling for the Azure SDK for Python" +readme = "README.md" +authors = [ + { name = "Microsoft Corporation", email = "azpysdkhelp@microsoft.com" } +] +urls = { "Homepage" = "https://github.com/Azure/azure-sdk-for-python" } + +dependencies = [ + "packaging", + "wheel", + "Jinja2", + "json-delta>=2.0", + "pytest-cov", + "pytest>=3.5.1", + "python-dotenv", + "PyYAML", + "urllib3", + "tomli-w==1.0.0", + "azure-core", + "ConfigArgParse>=0.12.0", + "pytest-asyncio>=0.9.0; python_version >= '3.5'", + "tomli; python_version < '3.11'", +] + +[project.scripts] +generate_package = "packaging_tools.generate_package:generate_main" +generate_sdk = "packaging_tools.generate_sdk:generate_main" +generate_client = "packaging_tools.generate_client:generate_main" +multiapi_combiner = "packaging_tools.multiapi_combiner:combine" +perfstress = "devtools_testutils.perfstress_tests:run_perfstress_cmd" +perfstressdebug = "devtools_testutils.perfstress_tests:run_perfstress_debug_cmd" +sdk_generator = "packaging_tools.sdk_generator:generate_main" +sdk_build = "ci_tools.build:build" +sdk_build_package = "ci_tools.build:build_package" +sdk_build_conda = "ci_tools.conda:entrypoint" +sdk_set_dev_version = "ci_tools.versioning.version_set_dev:version_set_dev_main" +sdk_set_version = "ci_tools.versioning.version_set:version_set_main" +sdk_increment_version = "ci_tools.versioning.version_increment:version_increment_main" +sdk_analyze_deps = "ci_tools.dependency_analysis:analyze_dependencies" +sdk_find_invalid_versions = "ci_tools.versioning.find_invalid_versions:find_invalid_versions_main" +sdk_verify_keywords = "ci_tools.keywords_verify:entrypoint" +systemperf = "devtools_testutils.perfstress_tests:run_system_perfstress_tests_cmd" +azpysdk = "azpysdk.main:main" + +[project.optional-dependencies] +build = ["six", "setuptools", "pyparsing", "certifi", "cibuildwheel", "pkginfo", "build"] +conda = ["beautifulsoup4"] +systemperf = ["aiohttp>=3.0", "requests>=2.0", "tornado==6.0.3", "httpx>=0.21", "azure-core"] +ghtools = ["GitPython", "PyGithub>=1.59.0", "requests>=2.0"] + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.packages.find] +where = ["."] +exclude = ["tests*"] + [tool.black] line-length=120 exclude="packaging_tools/templates/setup.py" diff --git a/eng/tools/azure-sdk-tools/setup.py b/eng/tools/azure-sdk-tools/setup.py deleted file mode 100644 index 5c12ef5d9f0b..000000000000 --- a/eng/tools/azure-sdk-tools/setup.py +++ /dev/null @@ -1,64 +0,0 @@ -import os -from setuptools import setup, find_packages - -# This is a "fake" package, meaning it's not supposed to be released but used -# locally with "pip install -e" - -DEPENDENCIES = [ - # Packaging - "packaging", - "wheel", - "Jinja2", - "json-delta>=2.0", - # Tests - "pytest-cov", - "pytest>=3.5.1", - "python-dotenv", - "PyYAML", - "urllib3", - "tomli-w==1.0.0", - "azure-core", - # Perf/Build - "ConfigArgParse>=0.12.0", -] - -setup( - name="azure-sdk-tools", - version="0.0.0", - author="Microsoft Corporation", - author_email="azpysdkhelp@microsoft.com", - url="https://github.com/Azure/azure-sdk-for-python", - packages=find_packages(), - long_description="Build and test tooling for the Azure SDK for Python", - install_requires=DEPENDENCIES, - include_package_data=True, - entry_points={ - "console_scripts": [ - "generate_package=packaging_tools.generate_package:generate_main", - "generate_sdk=packaging_tools.generate_sdk:generate_main", - "generate_client=packaging_tools.generate_client:generate_main", - "multiapi_combiner=packaging_tools.multiapi_combiner:combine", - "perfstress=devtools_testutils.perfstress_tests:run_perfstress_cmd", - "perfstressdebug=devtools_testutils.perfstress_tests:run_perfstress_debug_cmd", - "sdk_generator=packaging_tools.sdk_generator:generate_main", - "sdk_build=ci_tools.build:build", - "sdk_build_package=ci_tools.build:build_package", - "sdk_build_conda=ci_tools.conda:entrypoint", - "sdk_set_dev_version=ci_tools.versioning.version_set_dev:version_set_dev_main", - "sdk_set_version=ci_tools.versioning.version_set:version_set_main", - "sdk_increment_version=ci_tools.versioning.version_increment:version_increment_main", - "sdk_analyze_deps=ci_tools.dependency_analysis:analyze_dependencies", - "sdk_find_invalid_versions=ci_tools.versioning.find_invalid_versions:find_invalid_versions_main", - "sdk_verify_keywords=ci_tools.keywords_verify:entrypoint", - "systemperf=devtools_testutils.perfstress_tests:run_system_perfstress_tests_cmd", - ], - }, - extras_require={ - ":python_version>='3.5'": ["pytest-asyncio>=0.9.0"], - ":python_version<'3.11'": ["tomli"], - "build": ["six", "setuptools", "pyparsing", "certifi", "cibuildwheel", "pkginfo", "build"], - "conda": ["beautifulsoup4"], - "systemperf": ["aiohttp>=3.0", "requests>=2.0", "tornado==6.0.3", "httpx>=0.21", "azure-core"], - "ghtools": ["GitPython", "PyGithub>=1.59.0", "requests>=2.0"], - }, -) diff --git a/sdk/keyvault/azure-keyvault-keys/pyproject.toml b/sdk/keyvault/azure-keyvault-keys/pyproject.toml index 4b192dcb2eb6..eec044c8763e 100644 --- a/sdk/keyvault/azure-keyvault-keys/pyproject.toml +++ b/sdk/keyvault/azure-keyvault-keys/pyproject.toml @@ -46,3 +46,20 @@ pytyped = ["py.typed"] [tool.azure-sdk-build] pyright = false + +[tool.uv.sources] +azure-core = { path = "../../core/azure-core" } +azure-keyvault-nspkg = { path = "../../nspkg/azure-keyvault-nspkg" } +azure-sdk-tools = { path = "../../../eng/tools/azure-sdk-tools" } + +[dependency-groups] +dev = [ + "aiohttp>=3.0", + "azure-core", + "azure-identity>=1.24.0", + "azure-keyvault-nspkg", + "azure-mgmt-keyvault==10.1.0", + "azure-sdk-tools", + "parameterized>=0.7.3", + "python-dateutil>=2.8.0", +] From a9373f25208e1a3de50675de8946587b69767641 Mon Sep 17 00:00:00 2001 From: Scott Beddall Date: Thu, 21 Aug 2025 23:22:13 +0000 Subject: [PATCH 2/4] fix tests --- .../tests/test_parse_functionality.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/eng/tools/azure-sdk-tools/tests/test_parse_functionality.py b/eng/tools/azure-sdk-tools/tests/test_parse_functionality.py index b7328e76c0d5..1405850a0285 100644 --- a/eng/tools/azure-sdk-tools/tests/test_parse_functionality.py +++ b/eng/tools/azure-sdk-tools/tests/test_parse_functionality.py @@ -11,6 +11,7 @@ ) scenarios_folder = os.path.join(os.path.dirname(__file__), "integration", "scenarios") metapackage_scenario = os.path.join(scenarios_folder, "setup_py_metapackage") +setup_project_scenario = os.path.join(scenarios_folder, "setup_py_project_def") pyproject_scenario = os.path.join(scenarios_folder, "pyproject_project_def") pyproject_extension_scenario = os.path.join(scenarios_folder, "pyproject_project_def_with_extension") @@ -110,22 +111,21 @@ def test_sdk_sample_setup(test_patch): ) """ - result = ParsedSetup.from_path(package_root) + result = ParsedSetup.from_path(setup_project_scenario) assert result.name == "azure-core" assert result.version == "1.21.0" assert result.python_requires == ">=3.7" assert result.requires == ["requests>=2.18.4", "six>=1.11.0", "typing-extensions>=4.0.1"] assert result.is_new_sdk == True - assert result.setup_filename == os.path.join(package_root, "setup.py") + assert result.setup_filename == os.path.join(setup_project_scenario, "setup.py") assert "pytyped" in result.package_data assert result.include_package_data == True - assert result.folder == package_root + assert result.folder == setup_project_scenario assert len(result.classifiers) > 0 assert result.classifiers[0] == "Development Status :: 5 - Production/Stable" assert result.classifiers[5] == "Programming Language :: Python :: 3.8" assert result.keywords[0] == "azure sdk" - assert result.is_metapackage == False assert len(result.keywords) == 2 @@ -191,24 +191,23 @@ def test_parse_recognizes_extensions(test_patch): ) """ - result = ParsedSetup.from_path(package_root) + result = ParsedSetup.from_path(setup_project_scenario) assert result.name == "azure-storage-extensions" assert result.version == "1.21.0" assert result.python_requires == ">=3.7" assert result.requires == ["requests>=2.18.4", "six>=1.11.0", "typing-extensions>=4.0.1"] # todo resolve this conflict assert result.is_new_sdk == True - assert result.setup_filename == os.path.join(package_root, "setup.py") + assert result.setup_filename == os.path.join(setup_project_scenario, "setup.py") assert "pytyped" in result.package_data assert result.include_package_data == True - assert result.folder == package_root + assert result.folder == setup_project_scenario assert len(result.classifiers) > 0 assert result.classifiers[0] == "Development Status :: 5 - Production/Stable" assert result.classifiers[5] == "Programming Language :: Python :: 3.8" assert result.ext_package == "azure.storage.extensions" assert result.ext_modules is not None assert result.is_pyproject == False - assert result.is_metapackage == False assert len(result.ext_modules) == 1 assert str(type(result.ext_modules[0])) == "" From c9f85acef0035d2b621fc8bd2215b3e11741a544 Mon Sep 17 00:00:00 2001 From: Scott Beddall Date: Fri, 22 Aug 2025 01:18:28 +0000 Subject: [PATCH 3/4] fix dev_setup for the fact that azuresdk-tools isn't a setup.py package anymore --- scripts/dev_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dev_setup.py b/scripts/dev_setup.py index b901c4f0effe..12b79276b25b 100644 --- a/scripts/dev_setup.py +++ b/scripts/dev_setup.py @@ -75,7 +75,7 @@ def select_install_type(pkg, run_develop, exceptions): packages = { tuple(os.path.dirname(f).rsplit(os.sep, 1)) - for f in glob.glob(os.path.join(root_dir, "sdk/*/azure-*/setup.py")) + glob.glob(os.path.join(root_dir, "eng/tools/azure-*/setup.py")) + for f in glob.glob(os.path.join(root_dir, "sdk/*/azure-*/setup.py")) + glob.glob(os.path.join(root_dir, "eng/tools/azure-sdk-tools/")) } # [(base_folder, package_name), ...] to {package_name: base_folder, ...} packages = {package_name: base_folder for (base_folder, package_name) in packages} From be3776149f33ac376537a834d47d4c8a8e97e584 Mon Sep 17 00:00:00 2001 From: Scott Beddall <45376673+scbedd@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:57:27 -0700 Subject: [PATCH 4/4] Update eng/tools/azure-sdk-tools/pyproject.toml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: McCoy PatiƱo <39780829+mccoyp@users.noreply.github.com> --- eng/tools/azure-sdk-tools/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/tools/azure-sdk-tools/pyproject.toml b/eng/tools/azure-sdk-tools/pyproject.toml index fcb4bccc9ad2..90a2dc26f91d 100644 --- a/eng/tools/azure-sdk-tools/pyproject.toml +++ b/eng/tools/azure-sdk-tools/pyproject.toml @@ -50,7 +50,7 @@ systemperf = "devtools_testutils.perfstress_tests:run_system_perfstress_tests_cm azpysdk = "azpysdk.main:main" [project.optional-dependencies] -build = ["six", "setuptools", "pyparsing", "certifi", "cibuildwheel", "pkginfo", "build"] +build = ["setuptools", "pyparsing", "certifi", "cibuildwheel", "pkginfo", "build"] conda = ["beautifulsoup4"] systemperf = ["aiohttp>=3.0", "requests>=2.0", "tornado==6.0.3", "httpx>=0.21", "azure-core"] ghtools = ["GitPython", "PyGithub>=1.59.0", "requests>=2.0"]