Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add bump-recipe command #188

Merged
merged 37 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
80f0e18
add bump-recipe command
ForgottenProgramme Oct 9, 2024
c521e70
fix type error
ForgottenProgramme Oct 9, 2024
65ce20d
add test
ForgottenProgramme Oct 17, 2024
061307d
fix failing tests
ForgottenProgramme Oct 18, 2024
dee55f8
Update conda_recipe_manager/commands/bump_recipe.py
ForgottenProgramme Oct 22, 2024
d2fabce
add some suggestions from the code review
ForgottenProgramme Oct 23, 2024
1032adc
more changes based on previous code review
ForgottenProgramme Oct 23, 2024
e60a2d1
check if the build number was actually incremented
ForgottenProgramme Nov 4, 2024
7a1df7d
parametrize the test
ForgottenProgramme Nov 5, 2024
61537fa
Update tests/commands/test_bump_recipe.py
ForgottenProgramme Nov 5, 2024
ed058d1
Update tests/commands/test_bump_recipe.py
ForgottenProgramme Nov 5, 2024
bd5b201
Update tests/commands/test_bump_recipe.py
ForgottenProgramme Nov 5, 2024
110f9cf
Update tests/commands/test_bump_recipe.py
ForgottenProgramme Nov 5, 2024
d787955
Update tests/commands/test_bump_recipe.py
ForgottenProgramme Nov 5, 2024
9a97d01
Update `convert` to properly handle complex Jinja expressions (#176)
beeankha Oct 9, 2024
2821b0b
Fixes #186: Parser cannot handle addition in JINJA replacements (#191)
schuylermartin45 Oct 10, 2024
420c990
Python code Dependency Scanner Prototype (#180)
schuylermartin45 Oct 10, 2024
9239484
Add __init__ files to all test directories (#192)
beeankha Oct 10, 2024
7b21d59
v0.3.0 commit (#193)
schuylermartin45 Oct 11, 2024
23e8d3e
Forgot to include some minor changes in the v0.3.0 release commit (#194)
schuylermartin45 Oct 11, 2024
7d47f22
Updates the recipe doc link (#195)
schuylermartin45 Oct 11, 2024
ac922c7
Fixes #197 and adds regression tests. Partially fixes #190 (#199)
schuylermartin45 Oct 11, 2024
a1df8c3
Removes missed debug statement (#200)
schuylermartin45 Oct 11, 2024
9abc66f
🤖 updated file(s) (#201)
conda-bot Oct 14, 2024
3d3ba7b
v0.3.1 (#202)
schuylermartin45 Oct 15, 2024
2670596
Removes conda-forge channel (#204)
schuylermartin45 Oct 16, 2024
d52f53b
Test the `MessageTable` class (#196)
beeankha Oct 16, 2024
3184ec9
207 Refactor `RecipeParserDeps` (#209)
schuylermartin45 Oct 21, 2024
c09786f
v0.3.2 (#210)
schuylermartin45 Oct 21, 2024
2120725
Fixes `numpy {{numpy}}` dependency bug (#214)
schuylermartin45 Oct 23, 2024
e49cff1
v0.3.3 (#216)
schuylermartin45 Oct 23, 2024
eeb8f0d
v0.3.4 (#217)
schuylermartin45 Oct 23, 2024
4a243fd
Improves pytest config filter to be less aggressive (#223)
schuylermartin45 Oct 30, 2024
389722f
🤖 updated file(s) (#226)
conda-bot Nov 4, 2024
fa057f4
Incorporating user documentation feedback and simplifies the `Makefil…
schuylermartin45 Nov 5, 2024
1414cad
remove dangling else statements
ForgottenProgramme Nov 6, 2024
da105e0
Merge branch 'main' into bump-recipe
schuylermartin45 Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions conda_recipe_manager/commands/bump_recipe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
:Description: CLI for bumping build number in recipe files.
"""

from __future__ import annotations

import sys
from pathlib import Path
from typing import cast

import click

from conda_recipe_manager.commands.utils.print import print_err
from conda_recipe_manager.commands.utils.types import ExitCode
from conda_recipe_manager.parser.recipe_parser import RecipeParser
from conda_recipe_manager.types import JsonPatchType


# TODO Improve. In order for `click` to play nice with `pyfakefs`, we set `path_type=str` and delay converting to a
# `Path` instance. This is caused by how `click` uses decorators. See these links for more detail:
# - https://pytest-pyfakefs.readthedocs.io/en/latest/troubleshooting.html#pathlib-path-objects-created-outside-of-tests
# - https://github.com/pytest-dev/pyfakefs/discussions/605
@click.command(short_help="Bumps a recipe file to a new version.")
@click.argument("recipe_file_path", type=click.Path(exists=True, path_type=str))
ForgottenProgramme marked this conversation as resolved.
Show resolved Hide resolved
@click.option(
"--build-num",
is_flag=True,
help="Bump the build number by 1.",
)
def bump_recipe(recipe_file_path: str, build_num: bool) -> None:
"""
Bumps a recipe to a new version.

RECIPE_FILE_PATH: Path to the target recipe file
"""
try:
contents_recipe = Path(recipe_file_path).read_text(encoding="utf-8")
except IOError:
print_err(f"Couldn't read the given recipe file: {recipe_file_path}")
sys.exit(ExitCode.IO_ERROR)

try:
recipe_parser = RecipeParser(contents_recipe)
except Exception: # pylint: disable=broad-except
print_err("An error occurred while parsing the recipe file contents.")
sys.exit(ExitCode.PARSE_EXCEPTION)

if build_num:
ForgottenProgramme marked this conversation as resolved.
Show resolved Hide resolved
try:
build_number = recipe_parser.get_value("/build/number")
except KeyError:
print_err("`/build/number` key could not be found in the recipe.")
sys.exit(ExitCode.ILLEGAL_OPERATION)

if not isinstance(build_number, int):
print_err("Build number is not an integer.")
sys.exit(ExitCode.ILLEGAL_OPERATION)

required_patch_blob = cast(JsonPatchType, {"op": "replace", "path": "/build/number", "value": build_number + 1})

if not recipe_parser.patch(required_patch_blob):
print_err(f"Couldn't perform the patch: {required_patch_blob}.")
sys.exit(ExitCode.PARSE_EXCEPTION)

Path(recipe_file_path).write_text(recipe_parser.render(), encoding="utf-8")
ForgottenProgramme marked this conversation as resolved.
Show resolved Hide resolved
sys.exit(ExitCode.SUCCESS)
print_err("Sorry, the default bump behaviour has not been implemented yet.")
2 changes: 2 additions & 0 deletions conda_recipe_manager/commands/conda_recipe_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import click

from conda_recipe_manager.commands.bump_recipe import bump_recipe
from conda_recipe_manager.commands.convert import convert
from conda_recipe_manager.commands.graph import graph
from conda_recipe_manager.commands.patch import patch
Expand All @@ -24,6 +25,7 @@ def conda_recipe_manager() -> None:
conda_recipe_manager.add_command(graph)
conda_recipe_manager.add_command(rattler_bulk_build)
conda_recipe_manager.add_command(patch)
conda_recipe_manager.add_command(bump_recipe)


if __name__ == "__main__":
Expand Down
82 changes: 82 additions & 0 deletions tests/commands/test_bump_recipe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
:Description: Tests the `bump-recipe` CLI
"""

import pytest
from click.testing import CliRunner
from pyfakefs.fake_filesystem import FakeFilesystem

from conda_recipe_manager.commands import bump_recipe
from conda_recipe_manager.commands.utils.types import ExitCode
from conda_recipe_manager.parser.recipe_parser import RecipeParser
from tests.file_loading import get_test_path, load_recipe
from tests.smoke_testing import assert_cli_usage


def test_usage() -> None:
"""
Smoke test that ensures rendering of the help menu
"""
assert_cli_usage(bump_recipe.bump_recipe)


@pytest.mark.parametrize(
"recipe_file, expected_recipe_file",
[
("simple-recipe.yaml", "bump_recipe/build_num_1.yaml"),
("bump_recipe/build_num_1.yaml", "bump_recipe/build_num_2.yaml"),
("bump_recipe/build_num_42.yaml", "bump_recipe/build_num_43.yaml"),
("bump_recipe/build_num_-1.yaml", "simple-recipe.yaml"),
],
)
def test_bump_recipe_cli(fs: FakeFilesystem, recipe_file: str, expected_recipe_file: str) -> None:
"""
Test for the case when build number is successfully incremented by 1.

:param fs: `pyfakefs` Fixture used to replace the file system
ForgottenProgramme marked this conversation as resolved.
Show resolved Hide resolved
"""
runner = CliRunner()
fs.add_real_directory(get_test_path(), read_only=False)
schuylermartin45 marked this conversation as resolved.
Show resolved Hide resolved

recipe_file_path = get_test_path() / recipe_file
expected_recipe_file_path = get_test_path() / expected_recipe_file

result = runner.invoke(bump_recipe.bump_recipe, ["--build-num", str(recipe_file_path)])

parser = load_recipe(recipe_file_path, RecipeParser)
expected_parser = load_recipe(expected_recipe_file_path, RecipeParser)

assert parser == expected_parser
assert result.exit_code == ExitCode.SUCCESS
ForgottenProgramme marked this conversation as resolved.
Show resolved Hide resolved


def test_bump_build_num_not_int(fs: FakeFilesystem) -> None:
"""
Test that the command fails gracefully case when the build number is not an integer,
and we are trying to increment it.

:param fs: `pyfakefs` Fixture used to replace the file system
ForgottenProgramme marked this conversation as resolved.
Show resolved Hide resolved
"""

runner = CliRunner()
fs.add_real_directory(get_test_path(), read_only=False)

recipe_file_path = get_test_path() / "bump_recipe/non_int_build_num.yaml"

result = runner.invoke(bump_recipe.bump_recipe, ["--build-num", str(recipe_file_path)])
assert result.exit_code == ExitCode.ILLEGAL_OPERATION


def test_bump_build_num_key_not_found(fs: FakeFilesystem) -> None:
"""
Test that the command fails gracefully when the build number key is missing and we try to increment it's value.

:param fs: `pyfakefs` Fixture used to replace the file system
ForgottenProgramme marked this conversation as resolved.
Show resolved Hide resolved
"""

runner = CliRunner()
fs.add_real_directory(get_test_path(), read_only=False)

recipe_file_path = get_test_path() / "bump_recipe/no_build_num.yaml"
result = runner.invoke(bump_recipe.bump_recipe, ["--build-num", str(recipe_file_path)])
assert result.exit_code == ExitCode.ILLEGAL_OPERATION
53 changes: 53 additions & 0 deletions tests/test_aux_files/bump_recipe/build_num_-1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{% set zz_non_alpha_first = 42 %}
{% set name = "types-toml" %}
{% set version = "0.10.8.6" %}

package:
name: {{ name|lower }} # [unix]

build:
number: -1
skip: true # [py<37]
is_true: true

# Comment above a top-level structure
requirements:
empty_field1:
host:
- setuptools # [unix]
- fakereq # [unix] selector with comment
empty_field2: # [unix and win] # selector with comment with comment symbol
run:
- python # not a selector
empty_field3:

about:
summary: This is a small recipe for testing
description: |
This is a PEP '561 type stub package for the toml package.
It can be used by type-checking tools like mypy, pyright,
pytype, PyCharm, etc. to check code that uses toml.
license: Apache-2.0 AND MIT

multi_level:
list_1:
- foo
# Ensure a comment in a list is supported
- bar
list_2:
- cat
- bat
- mat
list_3:
- ls
- sl
- cowsay

test_var_usage:
foo: {{ version }}
bar:
- baz
- {{ zz_non_alpha_first }}
- blah
- This {{ name }} is silly
- last
53 changes: 53 additions & 0 deletions tests/test_aux_files/bump_recipe/build_num_1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{% set zz_non_alpha_first = 42 %}
{% set name = "types-toml" %}
{% set version = "0.10.8.6" %}

package:
name: {{ name|lower }} # [unix]

build:
number: 1
skip: true # [py<37]
is_true: true

# Comment above a top-level structure
requirements:
empty_field1:
host:
- setuptools # [unix]
- fakereq # [unix] selector with comment
empty_field2: # [unix and win] # selector with comment with comment symbol
run:
- python # not a selector
empty_field3:

about:
summary: This is a small recipe for testing
description: |
This is a PEP '561 type stub package for the toml package.
It can be used by type-checking tools like mypy, pyright,
pytype, PyCharm, etc. to check code that uses toml.
license: Apache-2.0 AND MIT

multi_level:
list_1:
- foo
# Ensure a comment in a list is supported
- bar
list_2:
- cat
- bat
- mat
list_3:
- ls
- sl
- cowsay

test_var_usage:
foo: {{ version }}
bar:
- baz
- {{ zz_non_alpha_first }}
- blah
- This {{ name }} is silly
- last
53 changes: 53 additions & 0 deletions tests/test_aux_files/bump_recipe/build_num_2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{% set zz_non_alpha_first = 42 %}
{% set name = "types-toml" %}
{% set version = "0.10.8.6" %}

package:
name: {{ name|lower }} # [unix]

build:
number: 2
skip: true # [py<37]
is_true: true

# Comment above a top-level structure
requirements:
empty_field1:
host:
- setuptools # [unix]
- fakereq # [unix] selector with comment
empty_field2: # [unix and win] # selector with comment with comment symbol
run:
- python # not a selector
empty_field3:

about:
summary: This is a small recipe for testing
description: |
This is a PEP '561 type stub package for the toml package.
It can be used by type-checking tools like mypy, pyright,
pytype, PyCharm, etc. to check code that uses toml.
license: Apache-2.0 AND MIT

multi_level:
list_1:
- foo
# Ensure a comment in a list is supported
- bar
list_2:
- cat
- bat
- mat
list_3:
- ls
- sl
- cowsay

test_var_usage:
foo: {{ version }}
bar:
- baz
- {{ zz_non_alpha_first }}
- blah
- This {{ name }} is silly
- last
53 changes: 53 additions & 0 deletions tests/test_aux_files/bump_recipe/build_num_42.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{% set zz_non_alpha_first = 42 %}
{% set name = "types-toml" %}
{% set version = "0.10.8.6" %}

package:
name: {{ name|lower }} # [unix]

build:
number: 42
skip: true # [py<37]
is_true: true

# Comment above a top-level structure
requirements:
empty_field1:
host:
- setuptools # [unix]
- fakereq # [unix] selector with comment
empty_field2: # [unix and win] # selector with comment with comment symbol
run:
- python # not a selector
empty_field3:

about:
summary: This is a small recipe for testing
description: |
This is a PEP '561 type stub package for the toml package.
It can be used by type-checking tools like mypy, pyright,
pytype, PyCharm, etc. to check code that uses toml.
license: Apache-2.0 AND MIT

multi_level:
list_1:
- foo
# Ensure a comment in a list is supported
- bar
list_2:
- cat
- bat
- mat
list_3:
- ls
- sl
- cowsay

test_var_usage:
foo: {{ version }}
bar:
- baz
- {{ zz_non_alpha_first }}
- blah
- This {{ name }} is silly
- last
Loading
Loading