Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/github_actions/dot-github/workflo…
Browse files Browse the repository at this point in the history
…ws/test-summary/action-2.4
  • Loading branch information
beeankha authored Jul 9, 2024
2 parents dd22a6b + 0c136f5 commit 17792da
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
GLOBAL: https://raw.githubusercontent.com/conda/infra/main/.github/global.yml
LOCAL: .github/labels.yml
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- id: has_local
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
with:
Expand Down
14 changes: 9 additions & 5 deletions conda_build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2886,18 +2886,22 @@ def warn_on_use_of_SRC_DIR(metadata):
)


@deprecated(
"3.16.0",
"24.7.0",
addendum=(
"Test built packages instead, not recipes "
"(e.g., `conda build --test package` instead of `conda build --test recipe/`)."
),
deprecation_type=FutureWarning, # we need to warn users, not developers
)
def _construct_metadata_for_test_from_recipe(recipe_dir, config):
config.need_cleanup = False
config.recipe_dir = None
hash_input = {}
metadata = expand_outputs(
render_recipe(recipe_dir, config=config, reset_build_id=False)
)[0][1]
log = utils.get_logger(__name__)
log.warning(
"Testing based on recipes is deprecated as of conda-build 3.16.0. Please adjust "
"your code to pass your desired conda package to test instead."
)

utils.rm_rf(metadata.config.test_dir)

Expand Down
13 changes: 11 additions & 2 deletions conda_build/deprecations.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def __call__(
*,
addendum: str | None = None,
stack: int = 0,
deprecation_type: type[Warning] = DeprecationWarning,
) -> Callable[[Callable[P, T]], Callable[P, T]]:
"""Deprecation decorator for functions, methods, & classes.
Expand All @@ -102,6 +103,7 @@ def deprecated_decorator(func: Callable[P, T]) -> Callable[P, T]:
remove_in=remove_in,
prefix=f"{func.__module__}.{func.__qualname__}",
addendum=addendum,
deprecation_type=deprecation_type,
)

# alert developer that it's time to remove something
Expand All @@ -128,6 +130,7 @@ def argument(
rename: str | None = None,
addendum: str | None = None,
stack: int = 0,
deprecation_type: type[Warning] = DeprecationWarning,
) -> Callable[[Callable[P, T]], Callable[P, T]]:
"""Deprecation decorator for keyword arguments.
Expand All @@ -149,6 +152,7 @@ def deprecated_decorator(func: Callable[P, T]) -> Callable[P, T]:
addendum=(
f"Use '{rename}' instead." if rename and not addendum else addendum
),
deprecation_type=deprecation_type,
)

# alert developer that it's time to remove something
Expand Down Expand Up @@ -181,6 +185,7 @@ def action(
*,
addendum: str | None = None,
stack: int = 0,
deprecation_type: type[Warning] = FutureWarning,
) -> ActionType:
"""Wraps any argparse.Action to issue a deprecation warning."""

Expand All @@ -203,7 +208,7 @@ def __init__(inner_self: Self, *args: Any, **kwargs: Any) -> None:
else f"`{inner_self.dest}`"
),
addendum=addendum,
deprecation_type=FutureWarning,
deprecation_type=deprecation_type,
)

# alert developer that it's time to remove something
Expand Down Expand Up @@ -263,6 +268,7 @@ def constant(
*,
addendum: str | None = None,
stack: int = 0,
deprecation_type: type[Warning] = DeprecationWarning,
) -> None:
"""Deprecation function for module constant/global.
Expand All @@ -281,6 +287,7 @@ def constant(
remove_in=remove_in,
prefix=f"{fullname}.{constant}",
addendum=addendum,
deprecation_type=deprecation_type,
)

# alert developer that it's time to remove something
Expand Down Expand Up @@ -310,6 +317,7 @@ def topic(
topic: str,
addendum: str | None = None,
stack: int = 0,
deprecation_type: type[Warning] = DeprecationWarning,
) -> None:
"""Deprecation function for a topic.
Expand All @@ -325,6 +333,7 @@ def topic(
remove_in=remove_in,
prefix=topic,
addendum=addendum,
deprecation_type=deprecation_type,
)

# alert developer that it's time to remove something
Expand Down Expand Up @@ -379,7 +388,7 @@ def _generate_message(
prefix: str,
addendum: str | None,
*,
deprecation_type: type[Warning] = DeprecationWarning,
deprecation_type: type[Warning],
) -> tuple[type[Warning] | None, str]:
"""Generate the standardized deprecation message and determine whether the
deprecation is pending, active, or past.
Expand Down
15 changes: 11 additions & 4 deletions conda_build/inspect_pkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from conda.core.prefix_data import PrefixData
from conda.models.records import PrefixRecord

from .exceptions import CondaBuildUserError
from .os_utils.ldd import (
get_linkages,
get_package_obj_files,
Expand Down Expand Up @@ -219,9 +220,13 @@ def inspect_linkages(
sysroot: str = "",
) -> str:
if not packages and not untracked and not all_packages:
sys.exit("At least one package or --untracked or --all must be provided")
raise CondaBuildUserError(
"At least one package or --untracked or --all must be provided"
)
elif on_win:
sys.exit("Error: conda inspect linkages is only implemented in Linux and OS X")
raise CondaBuildUserError(
"`conda inspect linkages` is only implemented on Linux and macOS"
)

prefix = Path(prefix)
installed = {prec.name: prec for prec in PrefixData(str(prefix)).iter_records()}
Expand All @@ -237,7 +242,7 @@ def inspect_linkages(
if name == untracked_package:
obj_files = get_untracked_obj_files(prefix)
elif name not in installed:
sys.exit(f"Package {name} is not installed in {prefix}")
raise CondaBuildUserError(f"Package {name} is not installed in {prefix}")
else:
obj_files = get_package_obj_files(installed[name], prefix)

Expand Down Expand Up @@ -308,7 +313,9 @@ def inspect_objects(
groupby: str = "package",
):
if not on_mac:
sys.exit("Error: conda inspect objects is only implemented in OS X")
raise CondaBuildUserError(
"`conda inspect objects` is only implemented on macOS"
)

prefix = Path(prefix)
installed = {prec.name: prec for prec in PrefixData(str(prefix)).iter_records()}
Expand Down
19 changes: 19 additions & 0 deletions news/3192-deprecate-testing-recipes
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* <news item>

### Deprecations

* Mark `conda_build.build._construct_metadata_for_test_from_recipe` as deprecated. Test built packages instead, not recipes (e.g., `conda build --test package` instead of `conda build --test recipe/`). (#3192 via #5352)

### Docs

* <news item>

### Other

* <news item>
5 changes: 3 additions & 2 deletions tests/cli/test_main_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from conda_build import api
from conda_build.cli import main_inspect
from conda_build.exceptions import CondaBuildUserError
from conda_build.utils import on_win

from ..utils import metadata_dir
Expand All @@ -23,7 +24,7 @@ def test_inspect_linkages(testing_workdir, capfd):
# get a package that has known object output
args = ["linkages", "python"]
if on_win:
with pytest.raises(SystemExit) as exc:
with pytest.raises(CondaBuildUserError) as exc:
main_inspect.execute(args)
assert "conda inspect linkages is only implemented in Linux and OS X" in exc
else:
Expand All @@ -36,7 +37,7 @@ def test_inspect_objects(testing_workdir, capfd):
# get a package that has known object output
args = ["objects", "python"]
if sys.platform != "darwin":
with pytest.raises(SystemExit) as exc:
with pytest.raises(CondaBuildUserError) as exc:
main_inspect.execute(args)
assert "conda inspect objects is only implemented in OS X" in exc
else:
Expand Down
13 changes: 12 additions & 1 deletion tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
from conda_build import api, build
from conda_build.exceptions import CondaBuildUserError

from .utils import get_noarch_python_meta, metadata_dir
from .utils import get_noarch_python_meta, metadata_dir, metadata_path

if TYPE_CHECKING:
from conda_build.config import Config

if TYPE_CHECKING:
from pytest_mock import MockerFixture
Expand Down Expand Up @@ -351,6 +354,14 @@ def test_copy_readme(testing_metadata: MetaData, readme: str):
assert Path(testing_metadata.config.info_dir, readme).exists()


def test_construct_metadata_for_test_from_recipe(testing_config: Config) -> None:
with pytest.warns(FutureWarning):
build._construct_metadata_for_test_from_recipe(
str(metadata_path / "test_source_files"),
testing_config,
)


@pytest.mark.skipif(not on_win, reason="WSL is only on Windows")
def test_wsl_unsupported(
testing_metadata: MetaData,
Expand Down
5 changes: 3 additions & 2 deletions tests/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
import pytest

from conda_build import api
from conda_build.exceptions import CondaBuildUserError


def test_inspect_linkages():
if sys.platform == "win32":
with pytest.raises(SystemExit) as exc:
with pytest.raises(CondaBuildUserError) as exc:
out_string = api.inspect_linkages("python")
assert "conda inspect linkages is only implemented in Linux and OS X" in exc
else:
Expand All @@ -20,7 +21,7 @@ def test_inspect_linkages():

def test_inspect_objects():
if sys.platform != "darwin":
with pytest.raises(SystemExit) as exc:
with pytest.raises(CondaBuildUserError) as exc:
out_string = api.inspect_objects("python")
assert "conda inspect objects is only implemented in OS X" in exc
else:
Expand Down
28 changes: 26 additions & 2 deletions tests/test_inspect_pkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
import pytest
from conda.core.prefix_data import PrefixData

from conda_build.inspect_pkg import which_package
from conda_build.utils import on_win
from conda_build.exceptions import CondaBuildUserError
from conda_build.inspect_pkg import inspect_linkages, inspect_objects, which_package
from conda_build.utils import on_mac, on_win


def test_which_package(tmp_path: Path):
Expand Down Expand Up @@ -271,3 +272,26 @@ def test_which_package_battery(tmp_path: Path):

# missing files should return no packages
assert not len(list(which_package(tmp_path / "missing", tmp_path)))


def test_inspect_linkages_no_packages():
with pytest.raises(CondaBuildUserError):
inspect_linkages([])


@pytest.mark.skipif(not on_win, reason="inspect_linkages is available")
def test_inspect_linkages_on_win():
with pytest.raises(CondaBuildUserError):
inspect_linkages(["packages"])


@pytest.mark.skipif(on_win, reason="inspect_linkages is not available")
def test_inspect_linkages_not_installed():
with pytest.raises(CondaBuildUserError):
inspect_linkages(["not_installed_pkg"])


@pytest.mark.skipif(on_mac, reason="inspect_objects is only available on macOS")
def test_inspect_objects_not_on_mac():
with pytest.raises(CondaBuildUserError):
inspect_objects([])
38 changes: 31 additions & 7 deletions tests/test_post.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import pytest

import conda_build.utils
from conda_build import api, post
from conda_build.utils import (
get_site_packages,
Expand Down Expand Up @@ -138,7 +139,7 @@ def test_menuinst_validation_fails_bad_schema(testing_config, caplog, tmp_path):
assert "ValidationError" in captured_text


def test_menuinst_validation_fails_bad_json(testing_config, caplog, tmp_path):
def test_menuinst_validation_fails_bad_json(testing_config, monkeypatch, tmp_path):
"3rd check - non-parsable JSON fails validation"
recipe = Path(metadata_dir, "_menu_json_validation")
recipe_tmp = tmp_path / "_menu_json_validation"
Expand All @@ -147,13 +148,36 @@ def test_menuinst_validation_fails_bad_json(testing_config, caplog, tmp_path):
menu_json_contents = menu_json.read_text()
menu_json.write_text(menu_json_contents + "Make this an invalid JSON")

with caplog.at_level(logging.WARNING):
api.build(str(recipe_tmp), config=testing_config, notest=True)
# suspect caplog fixture may fail; use monkeypatch instead.
records = []

captured_text = caplog.text
assert "Found 'Menu/*.json' files but couldn't validate:" not in captured_text
assert "not a valid menuinst JSON document" in captured_text
assert "JSONDecodeError" in captured_text
class MonkeyLogger:
def __getattr__(self, name):
return self.warning

def warning(self, *args, **kwargs):
records.append((*args, kwargs))

monkeylogger = MonkeyLogger()

def get_monkey_logger(*args, **kwargs):
return monkeylogger

# For some reason it uses get_logger in the individual functions, instead of
# a module-level global that we could easily patch.
monkeypatch.setattr(conda_build.utils, "get_logger", get_monkey_logger)

api.build(str(recipe_tmp), config=testing_config, notest=True)

# without %s substitution
messages = [record[0] for record in records]

assert "Found 'Menu/*.json' files but couldn't validate: %s" not in messages
assert "'%s' is not a valid menuinst JSON document!" in messages
assert any(
isinstance(record[-1].get("exc_info"), json.JSONDecodeError)
for record in records
)


def test_file_hash(testing_config, caplog, tmp_path):
Expand Down

0 comments on commit 17792da

Please sign in to comment.