From 24ec8db10864ba4d51badf46a3ac055478707400 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Sat, 1 Feb 2025 09:52:09 +0000 Subject: [PATCH 1/4] Add constraint key --- pyodide_build/recipe/builder.py | 32 ++++++++++++++++++- pyodide_build/recipe/spec.py | 1 + .../pkg_test_constraint/meta.yaml | 10 ++++++ .../pkg_test_constraint/src/pyproject.toml | 8 +++++ pyodide_build/tests/recipe/test_builder.py | 31 +++++++++++++++++- 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml create mode 100644 pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/src/pyproject.toml diff --git a/pyodide_build/recipe/builder.py b/pyodide_build/recipe/builder.py index a51e6f75..0cf77841 100755 --- a/pyodide_build/recipe/builder.py +++ b/pyodide_build/recipe/builder.py @@ -22,6 +22,7 @@ RUST_BUILD_PRELUDE, BuildArgs, get_build_environment_vars, + get_build_flag, get_pyodide_root, pyodide_tags, replace_so_abi_tags, @@ -335,7 +336,34 @@ def _download_and_extract(self) -> None: extract_dir_name = trim_archive_extension(tarballname) shutil.move(self.build_dir / extract_dir_name, self.src_extract_dir) - self.src_dist_dir.mkdir(parents=True, exist_ok=True) + self.src_dist_dir.mkdir(parents=True, exist_ok=True)\ + + def _override_constraints(self) -> str: + """ + Override global constraints (PIP_CONSTRAINT) with constraints specific to this package. + + returns the path to the new constraints file. + """ + try: + host_constraints = get_build_flag("PIP_CONSTRAINT") + except ValueError: + host_constraints = "" + + constraints = self.recipe.requirements.constraint + if not constraints: + # nothing to override + return host_constraints + + host_constraints_file = Path(host_constraints) + new_constraints_file = self.build_dir / "constraints.txt" + if host_constraints_file.is_file(): + shutil.copy(host_constraints_file, new_constraints_file) + + with new_constraints_file.open("a") as f: + for constraint in constraints: + f.write(constraint + "\n") + + return str(new_constraints_file) def _compile( self, @@ -383,6 +411,8 @@ def _compile( ) build_env = runner.env + build_env["PIP_CONSTRAINT"] = str(self._override_constraints()) + pypabuild.build( self.src_extract_dir, self.src_dist_dir, build_env, config_settings ) diff --git a/pyodide_build/recipe/spec.py b/pyodide_build/recipe/spec.py index ba2f5ef9..ff229d80 100644 --- a/pyodide_build/recipe/spec.py +++ b/pyodide_build/recipe/spec.py @@ -124,6 +124,7 @@ class _RequirementsSpec(BaseModel): run: list[str] = [] host: list[str] = [] executable: list[str] = [] + constraint: list[str] = [] model_config = ConfigDict(extra="forbid") diff --git a/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml b/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml new file mode 100644 index 00000000..1633afa9 --- /dev/null +++ b/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml @@ -0,0 +1,10 @@ +package: + name: pkg_test_constraint + version: "1.0.0" +requirements: + constraint: + - numpy < 2.0 + - scipy > 1.0 + - pytest == 7.0 +source: + path: src diff --git a/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/src/pyproject.toml b/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/src/pyproject.toml new file mode 100644 index 00000000..f032b1ce --- /dev/null +++ b/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/src/pyproject.toml @@ -0,0 +1,8 @@ +[build-system] +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "pkg_test_constraint" +version = "1.0.0" +authors = [] diff --git a/pyodide_build/tests/recipe/test_builder.py b/pyodide_build/tests/recipe/test_builder.py index b377bd71..91ccf075 100644 --- a/pyodide_build/tests/recipe/test_builder.py +++ b/pyodide_build/tests/recipe/test_builder.py @@ -8,7 +8,7 @@ import pytest from pyodide_build import common -from pyodide_build.build_env import BuildArgs +from pyodide_build.build_env import BuildArgs, get_build_flag from pyodide_build.recipe import builder as _builder from pyodide_build.recipe.builder import ( RecipeBuilder, @@ -216,6 +216,35 @@ def rlist(input_dir): assert n_moved == 3 +def test_override_constraints_no_override(tmp_path, dummy_xbuildenv): + builder = RecipeBuilder.get_builder( + recipe=RECIPE_DIR / "pkg_test_executable", # constraints not set, so no override + build_args=BuildArgs(), + build_dir=tmp_path, + ) + + path = builder._override_constraints() + assert path == get_build_flag("PIP_CONSTRAINT") + + +def test_override_constraints_override(tmp_path, dummy_xbuildenv): + builder = RecipeBuilder.get_builder( + recipe=RECIPE_DIR / "pkg_test_constraint", + build_args=BuildArgs(), + build_dir=tmp_path, + ) + + path = builder._override_constraints() + assert path == str(tmp_path / "constraints.txt") + + data = Path(path).read_text().strip().split("\n") + assert data[-3:] == [ + "numpy < 2.0", + "scipy > 1.0", + "pytest == 7.0" + ], data + + class MockSourceSpec(_SourceSpec): @pydantic.model_validator(mode="after") def _check_patches_extra(self) -> Self: From c2f21cd7341c8ab9d440d39644c851ec125e749d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 1 Feb 2025 09:54:50 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pyodide_build/recipe/builder.py | 2 +- pyodide_build/tests/recipe/test_builder.py | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pyodide_build/recipe/builder.py b/pyodide_build/recipe/builder.py index 0cf77841..ad1746b4 100755 --- a/pyodide_build/recipe/builder.py +++ b/pyodide_build/recipe/builder.py @@ -336,7 +336,7 @@ def _download_and_extract(self) -> None: extract_dir_name = trim_archive_extension(tarballname) shutil.move(self.build_dir / extract_dir_name, self.src_extract_dir) - self.src_dist_dir.mkdir(parents=True, exist_ok=True)\ + self.src_dist_dir.mkdir(parents=True, exist_ok=True) def _override_constraints(self) -> str: """ diff --git a/pyodide_build/tests/recipe/test_builder.py b/pyodide_build/tests/recipe/test_builder.py index 91ccf075..5557e1e7 100644 --- a/pyodide_build/tests/recipe/test_builder.py +++ b/pyodide_build/tests/recipe/test_builder.py @@ -218,7 +218,8 @@ def rlist(input_dir): def test_override_constraints_no_override(tmp_path, dummy_xbuildenv): builder = RecipeBuilder.get_builder( - recipe=RECIPE_DIR / "pkg_test_executable", # constraints not set, so no override + recipe=RECIPE_DIR + / "pkg_test_executable", # constraints not set, so no override build_args=BuildArgs(), build_dir=tmp_path, ) @@ -238,11 +239,7 @@ def test_override_constraints_override(tmp_path, dummy_xbuildenv): assert path == str(tmp_path / "constraints.txt") data = Path(path).read_text().strip().split("\n") - assert data[-3:] == [ - "numpy < 2.0", - "scipy > 1.0", - "pytest == 7.0" - ], data + assert data[-3:] == ["numpy < 2.0", "scipy > 1.0", "pytest == 7.0"], data class MockSourceSpec(_SourceSpec): From 4cf55ae7b285cd7068bd9546abf0e57911b4ee34 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Tue, 4 Feb 2025 09:25:20 +0000 Subject: [PATCH 3/4] Rename function --- pyodide_build/recipe/builder.py | 7 ++++--- .../recipe/_test_recipes/pkg_test_constraint/meta.yaml | 1 - pyodide_build/tests/recipe/test_builder.py | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyodide_build/recipe/builder.py b/pyodide_build/recipe/builder.py index ad1746b4..b0c49efa 100755 --- a/pyodide_build/recipe/builder.py +++ b/pyodide_build/recipe/builder.py @@ -338,9 +338,10 @@ def _download_and_extract(self) -> None: shutil.move(self.build_dir / extract_dir_name, self.src_extract_dir) self.src_dist_dir.mkdir(parents=True, exist_ok=True) - def _override_constraints(self) -> str: + def _create_constraints_file(self) -> str: """ - Override global constraints (PIP_CONSTRAINT) with constraints specific to this package. + Creates a pip constraints file by concatenating global constraints (PIP_CONSTRAINT) + with constraints specific to this package. returns the path to the new constraints file. """ @@ -411,7 +412,7 @@ def _compile( ) build_env = runner.env - build_env["PIP_CONSTRAINT"] = str(self._override_constraints()) + build_env["PIP_CONSTRAINT"] = str(self._create_constraints_file()) pypabuild.build( self.src_extract_dir, self.src_dist_dir, build_env, config_settings diff --git a/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml b/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml index 1633afa9..24782043 100644 --- a/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml +++ b/pyodide_build/tests/recipe/_test_recipes/pkg_test_constraint/meta.yaml @@ -4,7 +4,6 @@ package: requirements: constraint: - numpy < 2.0 - - scipy > 1.0 - pytest == 7.0 source: path: src diff --git a/pyodide_build/tests/recipe/test_builder.py b/pyodide_build/tests/recipe/test_builder.py index 5557e1e7..a0fdf2a7 100644 --- a/pyodide_build/tests/recipe/test_builder.py +++ b/pyodide_build/tests/recipe/test_builder.py @@ -216,7 +216,7 @@ def rlist(input_dir): assert n_moved == 3 -def test_override_constraints_no_override(tmp_path, dummy_xbuildenv): +def test_create_constraints_file_no_override(tmp_path, dummy_xbuildenv): builder = RecipeBuilder.get_builder( recipe=RECIPE_DIR / "pkg_test_executable", # constraints not set, so no override @@ -224,22 +224,22 @@ def test_override_constraints_no_override(tmp_path, dummy_xbuildenv): build_dir=tmp_path, ) - path = builder._override_constraints() + path = builder._create_constraints_file() assert path == get_build_flag("PIP_CONSTRAINT") -def test_override_constraints_override(tmp_path, dummy_xbuildenv): +def test_create_constraints_file_override(tmp_path, dummy_xbuildenv): builder = RecipeBuilder.get_builder( recipe=RECIPE_DIR / "pkg_test_constraint", build_args=BuildArgs(), build_dir=tmp_path, ) - path = builder._override_constraints() + path = builder._create_constraints_file() assert path == str(tmp_path / "constraints.txt") data = Path(path).read_text().strip().split("\n") - assert data[-3:] == ["numpy < 2.0", "scipy > 1.0", "pytest == 7.0"], data + assert data[-3:] == ["numpy < 2.0", "pytest == 7.0"], data class MockSourceSpec(_SourceSpec): From 6cc314c70b4657d5cafc3dfe86bb719737ba608e Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Tue, 4 Feb 2025 09:28:58 +0000 Subject: [PATCH 4/4] changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2667d32a..c87382da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.29.3] - 2025/02/04 + ### Added - Added new configuration variable `default_cross_build_env_url`. [#85](https://github.com/pyodide/pyodide-build/pull/85) +- Added a new recipe key `requirement.constraint` to set the package-level constraints. + [#97](https://github.com/pyodide/pyodide-build/pull/97) + ## [0.29.2] - 2024/11/29 ### Fixed