Skip to content

Commit ee7c203

Browse files
scbeddlmazuelCopilot
authored
Merge remainder of pyproject support (#41676)
* conglomerated improvements to support building and testing pure pyproject.toml packages --------- Co-authored-by: Laurent Mazuel <laurent.mazuel@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent c7d0845 commit ee7c203

File tree

11 files changed

+76
-17
lines changed

11 files changed

+76
-17
lines changed

eng/ci_tools.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ typing-extensions==4.12.2
1515
pyproject-api==1.8.0
1616
cibuildwheel==2.16.5
1717
importlib-metadata==8.5.0
18-
build==1.2.2
18+
build==1.2.2.post1
1919

2020
# requirements leveraged for testing
2121
pytest==8.3.5

eng/scripts/get_package_properties.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
# Use abspath for the os.walk because if setup parsing fails it often changes cwd which throws off the relative walk
4848
for root, dirs, files in os.walk(os.path.abspath(args.search_path)):
4949
if re.search(r"sdk[\\/][^\\/]+[\\/][^\\/]+$", root):
50-
if "setup.py" in files:
50+
if "setup.py" in files or "pyproject.toml" in files:
5151
try:
5252
parsed = ParsedSetup.from_path(root)
5353

eng/test_tools.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pytest-xdist==3.2.1
77
coverage==7.6.1
88
bandit==1.6.2
99
pyproject-api==1.8.0
10+
build==1.2.2.post1
1011

1112
# locking packages defined as deps from azure-sdk-tools
1213
Jinja2==3.1.6

eng/tox/install_depend_packages.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ def check_req_against_exclusion(req, req_to_exclude):
313313

314314

315315
def filter_dev_requirements(
316-
setup_py_path,
316+
package_directory,
317317
released_packages,
318318
temp_dir,
319319
additional_filter_fn: Optional[Callable[[str, List[str], List[Requirement]], List[str]]] = None,
@@ -326,7 +326,7 @@ def filter_dev_requirements(
326326
by the package).
327327
"""
328328
# This method returns list of requirements from dev_requirements by filtering out packages in given list
329-
dev_req_path = os.path.join(os.path.dirname(setup_py_path), DEV_REQ_FILE)
329+
dev_req_path = os.path.join(package_directory, DEV_REQ_FILE)
330330
requirements = []
331331
with open(dev_req_path, "r") as dev_req_file:
332332
requirements = dev_req_file.readlines()
@@ -350,7 +350,7 @@ def filter_dev_requirements(
350350

351351
if additional_filter_fn:
352352
# this filter function handles the case where a dev requirement is incompatible with the current set of targeted packages
353-
filtered_req = additional_filter_fn(setup_py_path, filtered_req, released_packages)
353+
filtered_req = additional_filter_fn(package_directory, filtered_req, released_packages)
354354

355355
logging.info("Filtered dev requirements: %s", filtered_req)
356356

@@ -408,10 +408,12 @@ def install_packages(packages, req_file):
408408
)
409409

410410
args = parser.parse_args()
411-
setup_path = os.path.join(os.path.abspath(args.target_package), "setup.py")
411+
412+
setup_path = os.path.join(os.path.abspath(args.target_package))
412413

413414
if not (os.path.exists(setup_path) and os.path.exists(args.work_dir)):
414415
logging.error("Invalid arguments. Please make sure target directory and working directory are valid path")
415416
sys.exit(1)
416417

418+
417419
install_dependent_packages(setup_path, args.dependency_type, args.work_dir)

eng/tox/tox.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# You can control which pip implementation is used by setting the TOX_PIP_IMPL environment variable:
1111
# - TOX_PIP_IMPL=pip (default) - Uses standard pip for package installation
1212
# - TOX_PIP_IMPL=uv - Uses uv pip for faster package installation
13-
#
13+
#
1414
# Example usage:
1515
# tox -e pylint # Use standard pip (default)
1616
# TOX_PIP_IMPL=pip tox -e pylint # Use standard pip explicitly
@@ -34,7 +34,6 @@ pip_command = {[tox]pip_impl}
3434
deps =
3535
-r {repository_root}/eng/test_tools.txt
3636

37-
3837
[coverage:paths]
3938
source =
4039
azure
@@ -60,6 +59,7 @@ pkgs =
6059
packaging==24.2
6160
urllib3==2.2.3
6261
tomli==2.2.1
62+
build==1.2.2.post1
6363

6464
[pytest]
6565
ignore_args=--ignore=.tox --ignore=build --ignore=.eggs --ignore=samples
@@ -430,7 +430,7 @@ deps =
430430
{[packaging]pkgs}
431431
commands =
432432
python -m {[tox]pip_command} install {repository_root}/tools/azure-sdk-tools --no-deps
433-
python {tox_root}/setup.py --q sdist -d {envtmpdir}
433+
sdk_build_package --package_folder {tox_root} -d {envtmpdir} --package_type sdist
434434
python {repository_root}/eng/tox/verify_sdist.py -d {envtmpdir} -t {tox_root}
435435

436436

eng/tox/verify_sdist.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def get_root_directories_in_sdist(dist_dir: str, version: str) -> List[str]:
4545
"""
4646
# find sdist zip file
4747
# extract sdist and find list of directories in sdist
48-
path_to_zip = glob.glob(os.path.join(dist_dir, "*{}*.tar.gz".format(version)))[0]
48+
path_to_zip = glob.glob(os.path.join(dist_dir, "**", "*{}*.tar.gz".format(version)), recursive=True)[0]
4949
extract_location = os.path.join(dist_dir, "unzipped")
5050
# Cleanup any files in unzipped
5151
cleanup(extract_location)

tools/azure-sdk-tools/ci_tools/build.py

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,57 @@
1010
from ci_tools.versioning.version_set_dev import get_dev_version, format_build_id
1111

1212

13+
def build_package() -> None:
14+
parser = argparse.ArgumentParser(
15+
description="""This is a secondary entrypoint for the "build" action. This command is used to install dependencies and build a specific package within the azure-sdk-for-python repository.""",
16+
)
17+
18+
parser.add_argument(
19+
"-d",
20+
"--distribution-directory",
21+
dest="distribution_directory",
22+
help="The path to the distribution directory. Should be passed $(Build.ArtifactStagingDirectory) from the devops yaml definition."
23+
+ "If that is not provided, will default to env variable SDK_ARTIFACT_DIRECTORY -> <calculated_repo_root>/.artifacts.",
24+
)
25+
26+
parser.add_argument(
27+
"--package_folder",
28+
dest="package_folder",
29+
required=True,
30+
help="The target that should be assembled",
31+
)
32+
33+
parser.add_argument(
34+
"--package_type",
35+
dest="package_type",
36+
choices=["sdist", "whl", "all"],
37+
default="all",
38+
help="The type of package to build: sdist (source distribution only), whl (wheel only), or all (both)",
39+
)
40+
41+
args = parser.parse_args()
42+
43+
target_package = ParsedSetup.from_path(args.package_folder)
44+
artifact_directory = get_artifact_directory(args.distribution_directory)
45+
46+
enable_sdist = True
47+
enable_wheel = True
48+
49+
if args.package_type == "sdist":
50+
enable_wheel = False
51+
52+
if args.package_type == "whl":
53+
enable_sdist = False
54+
55+
build_packages(
56+
[target_package.folder],
57+
artifact_directory,
58+
False,
59+
DEFAULT_BUILD_ID,
60+
enable_wheel,
61+
enable_sdist
62+
)
63+
1364
def build() -> None:
1465
parser = argparse.ArgumentParser(
1566
description="""This is the primary entrypoint for the "build" action. This command is used to build any package within the azure-sdk-for-python repository.""",
@@ -125,6 +176,8 @@ def build() -> None:
125176
artifact_directory,
126177
str_to_bool(args.is_dev_build),
127178
build_id,
179+
True,
180+
True
128181
)
129182

130183

@@ -146,6 +199,8 @@ def build_packages(
146199
distribution_directory: Optional[str] = None,
147200
is_dev_build: bool = False,
148201
build_id: str = "",
202+
enable_wheel: bool = True,
203+
enable_sdist: bool = True
149204
):
150205
logging.log(level=logging.INFO, msg=f"Generating {targeted_packages} using python{sys.version}")
151206

@@ -168,7 +223,7 @@ def build_packages(
168223
set_version_py(setup_parsed.setup_filename, new_version)
169224
set_dev_classifier(setup_parsed.setup_filename, new_version)
170225

171-
create_package(package_root, dist_dir)
226+
create_package(package_root, dist_dir, enable_wheel, enable_sdist)
172227

173228

174229
def create_package(
@@ -193,7 +248,7 @@ def create_package(
193248
pip_output = get_pip_list_output(sys.executable)
194249
necessary_install_requirements = [req for req in setup_parsed.requires if parse_require(req).key not in pip_output.keys()]
195250
run([sys.executable, "-m", "pip", "install", *necessary_install_requirements], cwd=setup_parsed.folder)
196-
run([sys.executable, "-m", "build", f"-n{'s' if enable_sdist else ''}{'w' if enable_wheel else ''}", "-o", dist], cwd=setup_parsed.folder)
251+
run([sys.executable, "-m", "build", f"-n{'s' if enable_sdist else ''}{'w' if enable_wheel else ''}", "-o", dist], cwd=setup_parsed.folder, check=True)
197252
else:
198253
if enable_wheel:
199254
if setup_parsed.ext_modules:

tools/azure-sdk-tools/ci_tools/functions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ def process_requires(setup_py_path: str, is_dev_build: bool = False):
404404
else:
405405
logging.info("Packages not available on PyPI:{}".format(requirement_to_update))
406406
update_requires(setup_py_path, requirement_to_update)
407-
logging.info("Package requirement is updated in setup.py")
407+
logging.info(f"Package requirement is updated in {'pyproject.toml' if pkg_details.is_pyproject else 'setup.py'}.")
408408

409409

410410
def find_sdist(dist_dir: str, pkg_name: str, pkg_version: str) -> Optional[str]:

tools/azure-sdk-tools/ci_tools/parsing/parse_functions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ def parse_pyproject(
394394
python_requires = project_config.get("requires-python")
395395
requires = project_config.get("dependencies")
396396
is_new_sdk = name in NEW_REQ_PACKAGES or any(map(lambda x: (parse_require(x).key in NEW_REQ_PACKAGES), requires))
397+
397398
name_space = name.replace("-", ".")
398399
package_data = get_value_from_dict(toml_dict, "tool.setuptools.package-data", None)
399400
include_package_data = get_value_from_dict(toml_dict, "tool.setuptools.include-package-data", True)

tools/azure-sdk-tools/ci_tools/scenario/generation.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ def create_package_and_install(
5151

5252
commands_options = []
5353
built_pkg_path = ""
54-
setup_py_path = os.path.join(target_setup, "setup.py")
5554
additional_downloaded_reqs = []
5655

5756
if not os.path.exists(distribution_directory):
@@ -68,10 +67,10 @@ def create_package_and_install(
6867
if cache_dir:
6968
commands_options.extend(["--cache-dir", cache_dir])
7069

71-
target_package = ParsedSetup.from_path(setup_py_path)
70+
target_package = ParsedSetup.from_path(target_setup)
7271

7372
discovered_packages = discover_packages(
74-
setup_py_path, distribution_directory, target_setup, package_type, force_create
73+
target_setup, distribution_directory, target_setup, package_type, force_create
7574
)
7675

7776
# ensure that discovered packages are always copied to the distribution directory regardless of other factors
@@ -104,7 +103,7 @@ def create_package_and_install(
104103
logging.info("Installing {w} from fresh built package.".format(w=built_package))
105104

106105
if not pre_download_disabled:
107-
requirements = ParsedSetup.from_path(os.path.join(os.path.abspath(target_setup), "setup.py")).requires
106+
requirements = ParsedSetup.from_path(os.path.join(os.path.abspath(target_setup))).requires
108107
azure_requirements = [req.split(";")[0] for req in requirements if req.startswith("azure-")]
109108

110109
if azure_requirements:

0 commit comments

Comments
 (0)