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

Inline fixtures in tests/test_variants.py #4714

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 0 additions & 21 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,27 +188,6 @@ def testing_env(testing_workdir, request, monkeypatch):
return env_path


# these are functions so that they get regenerated each time we use them.
# They could be fixtures, I guess.
@pytest.fixture(scope="function")
def numpy_version_ignored():
return {
"python": ["2.7.*", "3.5.*"],
"numpy": ["1.10.*", "1.11.*"],
"ignore_version": ["numpy"],
}


@pytest.fixture(scope="function")
def single_version():
return {"python": "2.7.*", "numpy": "1.11.*"}


@pytest.fixture(scope="function")
def no_numpy_version():
return {"python": ["2.7.*", "3.5.*"]}


@pytest.fixture(
scope="function",
params=[{}, {"MACOSX_DEPLOYMENT_TARGET": ["10.9"]}] if on_mac else [{}],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package:
name: ignore_version_reduces_matrix
version: 1.0

requirements:
build:
- packageA
- packageB { packageB }
run:
- packageA
- packageB

This file was deleted.

12 changes: 0 additions & 12 deletions tests/test-recipes/variants/03_numpy_matrix/meta.yaml

This file was deleted.

183 changes: 90 additions & 93 deletions tests/test_variants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Copyright (C) 2014 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause
from collections import OrderedDict
import json
import os
from pathlib import Path
Expand All @@ -10,113 +9,111 @@
import pytest
import yaml

from conda_build import api, exceptions, variants
from conda_build.utils import package_has_file
from conda_build import api, exceptions
from conda_build.variants import (
combine_specs,
dict_of_lists_to_list_of_dicts,
get_package_variants,
validate_spec,
)
from conda_build.utils import ensure_list, package_has_file

from .utils import variants_dir


def test_later_spec_priority(single_version, no_numpy_version):
# override a single key
specs = OrderedDict()
specs['no_numpy'] = no_numpy_version
specs['single_ver'] = single_version

combined_spec = variants.combine_specs(specs)
assert len(combined_spec) == 2
assert combined_spec["python"] == ["2.7.*"]

# keep keys that are not overwritten
specs = OrderedDict()
specs['single_ver'] = single_version
specs['no_numpy'] = no_numpy_version
combined_spec = variants.combine_specs(specs)
assert len(combined_spec) == 2
assert len(combined_spec["python"]) == 2


def test_get_package_variants_from_file(
testing_workdir, testing_config, no_numpy_version
):
variants_path = Path(testing_workdir, "variant_example.yaml")
variants_path.write_text(yaml.dump(no_numpy_version, default_flow_style=False))
@pytest.mark.parametrize(
"variants",
[
(["1.2", "3.4"], "5.6"),
("1.2", ["3.4", "5.6"]),
],
)
def test_spec_priority_overriding(variants):
name = "package"

first, second = variants
ordered_specs = {
"first": {name: first},
"second": {name: second},
}

testing_config.variant_config_files = [str(variants_path)]
combined = combine_specs(ordered_specs)[name]
expected = ensure_list(second)
assert len(combined) == len(expected)
assert combined == expected


@pytest.mark.parametrize(
"as_yaml",
[
pytest.param(True, id="yaml"),
pytest.param(False, id="dict"),
],
)
def test_python_variants(testing_workdir, testing_config, as_yaml):
"""Python variants are treated differently in conda recipes. Instead of being pinned against a
specific version they are converted into version ranges. E.g.:

python 3.5 -> python >=3.5,<3.6.0a0
otherPackages 3.5 -> otherPackages 3.5
"""
variants = {"python": ["3.9", "3.10"]}
testing_config.ignore_system_config = True

# write variants to disk
if as_yaml:
variants_path = Path(testing_workdir, "variant_example.yaml")
variants_path.write_text(yaml.dump(variants, default_flow_style=False))
testing_config.variant_config_files = [str(variants_path)]

# render the metadata
metadata = api.render(
os.path.join(variants_dir, "variant_recipe"),
no_download_source=False,
config=testing_config,
# if variants were written to disk then don't pass it along
variants=None if as_yaml else variants,
)

# one for each Python version. Numpy is not strictly pinned and should present only 1 dimension
# we should have one package/metadata per python version
assert len(metadata) == 2
assert (
sum(
"python >=2.7,<2.8" in req
for (m, _, _) in metadata
for req in m.meta["requirements"]["run"]
)
== 1
)
assert (
sum(
"python >=3.5,<3.6" in req
for (m, _, _) in metadata
for req in m.meta["requirements"]["run"]
)
== 1
)
# there should only be one run requirement for each package/metadata
assert len(metadata[0][0].meta["requirements"]["run"]) == 1
assert len(metadata[1][0].meta["requirements"]["run"]) == 1
# the run requirements should be python ranges
assert {
*metadata[0][0].meta["requirements"]["run"],
*metadata[1][0].meta["requirements"]["run"],
} == {"python >=3.9,<3.10.0a0", "python >=3.10,<3.11.0a0"}


def test_use_selectors_in_variants(testing_workdir, testing_config):
testing_config.variant_config_files = [
os.path.join(variants_dir, "selector_conda_build_config.yaml")
]
variants.get_package_variants(testing_workdir, testing_config)


def test_get_package_variants_from_dictionary_of_lists(testing_config, no_numpy_version):
testing_config.ignore_system_config = True
get_package_variants(testing_workdir, testing_config)

metadata = api.render(
os.path.join(variants_dir, "variant_recipe"),
no_download_source=False,
config=testing_config,
variants=no_numpy_version,
)

# one for each Python version. Numpy is not strictly pinned and should present only 1 dimension
assert len(metadata) == 2, metadata
assert (
sum(
"python >=2.7,<2.8" in req
for (m, _, _) in metadata
for req in m.meta["requirements"]["run"]
)
== 1
@pytest.mark.xfail(
reason=(
"7/19/2017 Strange failure. Can't reproduce locally. Test runs fine "
"with parallelism and everything. Test fails reproducibly on CI, but logging "
"into appveyor after failed run, test passes."
"1/9/2023 ignore_version doesn't work as advertised."
)
assert (
sum(
"python >=3.5,<3.6" in req
for (m, _, _) in metadata
for req in m.meta["requirements"]["run"]
)
== 1
)
def test_variant_with_ignore_version_reduces_matrix():
metadata = api.render(
os.path.join(variants_dir, "03_ignore_version_reduces_matrix"),
variants={
"packageA": ["1.2", "3.4"],
"packageB": ["5.6", "7.8"],
# packageB is ignored so that dimension should get collapsed
"ignore_version": "packageB",
},
finalize=False,
)


@pytest.mark.xfail(reason="Strange failure 7/19/2017. Can't reproduce locally. Test runs fine "
"with parallelism and everything. Test fails reproducibly on CI, but logging "
"into appveyor after failed run, test passes. =(")
def test_variant_with_ignore_numpy_version_reduces_matrix(numpy_version_ignored):
# variants are defined in yaml file in this folder
# there are two python versions and two numpy versions. However, because numpy is not pinned,
# the numpy dimensions should get collapsed.
recipe = os.path.join(variants_dir, "03_numpy_matrix")
metadata = api.render(recipe, variants=numpy_version_ignored, finalize=False)
assert len(metadata) == 2, metadata
assert len(metadata) == 2


def test_variant_with_numpy_pinned_has_matrix():
Expand Down Expand Up @@ -152,7 +149,7 @@ def test_no_satisfiable_variants_raises_error():
def test_zip_fields():
"""Zipping keys together allows people to tie different versions as sets of combinations."""
v = {'python': ['2.7', '3.5'], 'vc': ['9', '14'], 'zip_keys': [('python', 'vc')]}
ld = variants.dict_of_lists_to_list_of_dicts(v)
ld = dict_of_lists_to_list_of_dicts(v)
assert len(ld) == 2
assert ld[0]['python'] == '2.7'
assert ld[0]['vc'] == '9'
Expand All @@ -161,7 +158,7 @@ def test_zip_fields():

# allow duplication of values, but lengths of lists must always match
v = {'python': ['2.7', '2.7'], 'vc': ['9', '14'], 'zip_keys': [('python', 'vc')]}
ld = variants.dict_of_lists_to_list_of_dicts(v)
ld = dict_of_lists_to_list_of_dicts(v)
assert len(ld) == 2
assert ld[0]['python'] == '2.7'
assert ld[0]['vc'] == '9'
Expand Down Expand Up @@ -189,33 +186,33 @@ def test_validate_spec():
"corge": 42,
}
# valid spec
variants.validate_spec("spec", spec)
validate_spec("spec", spec)

spec2 = dict(spec)
spec2["bad-char"] = "bad-char"
# invalid characters
with pytest.raises(ValueError):
variants.validate_spec("spec[bad_char]", spec2)
validate_spec("spec[bad_char]", spec2)

spec3 = dict(spec, zip_keys="bad_zip_keys")
# bad zip_keys
with pytest.raises(ValueError):
variants.validate_spec("spec[bad_zip_keys]", spec3)
validate_spec("spec[bad_zip_keys]", spec3)

spec4 = dict(spec, zip_keys=[["bar", "baz"], ["qux", "quux"], ["quuz", "missing"]])
# zip_keys' zip_group has key missing from spec
with pytest.raises(ValueError):
variants.validate_spec("spec[missing_key]", spec4)
validate_spec("spec[missing_key]", spec4)

spec5 = dict(spec, zip_keys=[["bar", "baz"], ["qux", "quux", "quuz"], ["quuz"]])
# zip_keys' zip_group has duplicate key
with pytest.raises(ValueError):
variants.validate_spec("spec[duplicate_key]", spec5)
validate_spec("spec[duplicate_key]", spec5)

spec6 = dict(spec, baz=[4, 6])
# zip_keys' zip_group key fields have same length
with pytest.raises(ValueError):
variants.validate_spec("spec[duplicate_key]", spec6)
validate_spec("spec[duplicate_key]", spec6)


def test_cross_compilers():
Expand Down Expand Up @@ -261,7 +258,7 @@ def test_variant_input_with_zip_keys_keeps_zip_keys_list():
'zip_keys': ['sqlite', 'zlib', 'xz'],
'pin_run_as_build': {'python': {'min_pin': 'x.x', 'max_pin': 'x.x'}}
}
vrnts = variants.dict_of_lists_to_list_of_dicts(spec)
vrnts = dict_of_lists_to_list_of_dicts(spec)
assert len(vrnts) == 2
assert vrnts[0].get("zip_keys") == spec["zip_keys"]

Expand Down