-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3009 from wolfv/build-number
feat: add build number editing for v1 recipes
- Loading branch information
Showing
9 changed files
with
187 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .build_number import update_build_number | ||
|
||
__all__ = ["update_build_number"] |
103 changes: 103 additions & 0 deletions
103
conda_forge_tick/update_recipe/v1_recipe/build_number.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
from __future__ import annotations | ||
|
||
import io | ||
import logging | ||
import re | ||
from typing import TYPE_CHECKING, Any, Callable, Literal | ||
|
||
from conda_forge_tick.recipe_parser._parser import _get_yaml_parser | ||
|
||
if TYPE_CHECKING: | ||
from pathlib import Path | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
HashType = Literal["md5", "sha256"] | ||
|
||
RE_PATTERN = re.compile(r"(?:build|build_number|number):\s*(\d+)") | ||
|
||
|
||
def old_build_number(recipe_text: str) -> int: | ||
""" | ||
Extract the build number from the recipe text. | ||
Arguments: | ||
---------- | ||
* `recipe_text` - The recipe text. | ||
Returns: | ||
-------- | ||
* The build number. | ||
""" | ||
match = re.search(RE_PATTERN, recipe_text) | ||
if match is not None: | ||
return int(match.group(1)) | ||
return 0 | ||
|
||
|
||
def _update_build_number_in_context( | ||
recipe: dict[str, Any], new_build_number: int | ||
) -> bool: | ||
for key in recipe.get("context", {}): | ||
if key in {"build_number", "build", "number"}: | ||
recipe["context"][key] = new_build_number | ||
return True | ||
return False | ||
|
||
|
||
def _update_build_number_in_recipe( | ||
recipe: dict[str, Any], new_build_number: int | ||
) -> bool: | ||
is_modified = False | ||
if "build" in recipe and "number" in recipe["build"]: | ||
recipe["build"]["number"] = new_build_number | ||
is_modified = True | ||
|
||
if "outputs" in recipe: | ||
for output in recipe["outputs"]: | ||
if "build" in output and "number" in output["build"]: | ||
output["build"]["number"] = new_build_number | ||
is_modified = True | ||
|
||
return is_modified | ||
|
||
|
||
def _load_yaml(file: Path): | ||
yaml = _get_yaml_parser(typ="rt") | ||
with file.open("r") as f: | ||
return yaml.load(f) | ||
|
||
|
||
def _dump_yaml_to_str(data: dict) -> str: | ||
"""Dump a dictionary to a YAML string.""" | ||
yaml = _get_yaml_parser(typ="rt") | ||
with io.StringIO() as f: | ||
yaml.dump(data, f) | ||
return f.getvalue() | ||
|
||
|
||
def update_build_number(file: Path, new_build_number: int | Callable = 0) -> str: | ||
""" | ||
Update the build number in the recipe file. | ||
Arguments: | ||
---------- | ||
* `file` - The path to the recipe file. | ||
* `new_build_number` - The new build number to use. (default: 0) | ||
Returns: | ||
-------- | ||
* The updated recipe as a string. | ||
""" | ||
data = _load_yaml(file) | ||
|
||
if callable(new_build_number): | ||
detected_build_number = old_build_number(file.read_text()) | ||
new_build_number = new_build_number(detected_build_number) | ||
|
||
build_number_modified = _update_build_number_in_context(data, new_build_number) | ||
|
||
if not build_number_modified: | ||
_update_build_number_in_recipe(data, new_build_number) | ||
|
||
return _dump_yaml_to_str(data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# set the build number to something | ||
context: | ||
build: 0 | ||
|
||
package: | ||
name: recipe_1 | ||
version: "0.1.0" | ||
|
||
build: | ||
number: ${{ build }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# set the build number to something | ||
context: | ||
build: 123 | ||
|
||
package: | ||
name: recipe_1 | ||
version: "0.1.0" | ||
|
||
build: | ||
number: ${{ build }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# set the build number to something | ||
package: | ||
name: recipe_1 | ||
version: "0.1.0" | ||
|
||
# set the build number to something directly in the recipe text | ||
build: | ||
number: 0 | ||
|
||
source: | ||
- url: foo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# set the build number to something | ||
package: | ||
name: recipe_1 | ||
version: "0.1.0" | ||
|
||
# set the build number to something directly in the recipe text | ||
build: | ||
number: 321 | ||
|
||
source: | ||
- url: foo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
from conda_forge_tick.update_recipe.v1_recipe import update_build_number | ||
|
||
|
||
@pytest.fixture | ||
def data_dir() -> Path: | ||
return Path(__file__).parent / "recipe_v1" | ||
|
||
|
||
def test_build_number_mod(data_dir: Path) -> None: | ||
tests = data_dir / "build_number" | ||
result = update_build_number(tests / "test_1/recipe.yaml", 0) | ||
expected = tests / "test_1/expected.yaml" | ||
assert result == expected.read_text() | ||
|
||
result = update_build_number(tests / "test_2/recipe.yaml", 0) | ||
expected = tests / "test_2/expected.yaml" | ||
assert result == expected.read_text() |