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

Continue on missing variant packages #1550

Merged
1 change: 1 addition & 0 deletions src/rez/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ def _parse_env_var(self, value):
"alias_back": OptionalStr,
"package_preprocess_function": OptionalStrOrFunction,
"package_preprocess_mode": PreprocessMode_,
"error_on_missing_variant_requires": Bool,
"context_tracking_host": OptionalStr,
"variant_shortlinks_dirname": OptionalStr,
"build_thread_count": BuildThreadCount_,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name = "missing_variant_requires"
version = "1"

def commands():
pass

variants = [
["noexist"],
["nada"]
]
12 changes: 11 additions & 1 deletion src/rez/rezconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,17 @@
# this value is False.
allow_unversioned_packages = True

# Defines whether a resolve should immediately fail if any variants have a required package that can't be found.
# This can be useful to disable if you have packages that aren't available to all users.
# It is enabled by default. If a variant has requires that cannot be found , it will error immediately rather than
# trying the other variants.
# If disabled, it will try other variants before giving up.
#
# .. warning::
JeanChristopheMorinPerso marked this conversation as resolved.
Show resolved Hide resolved
# Memcached isn't tested with scenarios where you expect users to have access to different sets of packages.
# It expects that every user can access the same set of packages, which may cause incorrect resolves
# when this option is disabled.
error_on_missing_variant_requires = True

###############################################################################
# Environment Resolution
Expand Down Expand Up @@ -657,7 +668,6 @@
# - "override": Package's preprocess function completely overrides the global preprocess.
package_preprocess_mode = "override"


###############################################################################
# Context Tracking
###############################################################################
Expand Down
15 changes: 11 additions & 4 deletions src/rez/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1383,10 +1383,14 @@ def _create_phase(status=None):
# Raise with more info when match found
searched = "; ".join(self.solver.package_paths)
requested = ", ".join(requesters)

fail_message = ("package family not found: {}, was required by: {} (searched: {})"
.format(req.name, requested, searched))
if not config.error_on_missing_variant_requires:
print(fail_message, file=sys.stderr)
return _create_phase(SolverStatus.failed)
raise PackageFamilyNotFoundError(
"package family not found: %s, "
"was required by: %s (searched: %s)"
% (req.name, requested, searched))
fail_message)

scopes.append(scope)
if self.pr:
Expand Down Expand Up @@ -2398,7 +2402,10 @@ def _get_failed_phase(self, index=None):
except IndexError:
raise IndexError("failure index out of range")

fail_description = phase.failure_reason.description()
if phase.failure_reason is None:
fail_description = "Solver failed with unknown reason."
else:
fail_description = phase.failure_reason.description()
if prepend_abort_reason and self.abort_reason:
fail_description = "%s:\n%s" % (self.abort_reason, fail_description)

Expand Down
2 changes: 1 addition & 1 deletion src/rez/tests/test_completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _eq(prefix, expected_completions):
_eq("", ["bahish", "nada", "nopy", "pybah", "pydad", "pyfoo", "pymum",
"pyodd", "pyson", "pysplit", "python", "pyvariants",
"test_variant_split_start", "test_variant_split_mid1",
"test_variant_split_mid2", "test_variant_split_end"])
"test_variant_split_mid2", "test_variant_split_end", "missing_variant_requires"])
_eq("py", ["pybah", "pydad", "pyfoo", "pymum", "pyodd", "pyson",
"pysplit", "python", "pyvariants"])
_eq("pys", ["pyson", "pysplit"])
Expand Down
3 changes: 2 additions & 1 deletion src/rez/tests/test_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
'late_binding-1.0',
'timestamped-1.0.5', 'timestamped-1.0.6', 'timestamped-1.1.0', 'timestamped-1.1.1',
'timestamped-1.2.0', 'timestamped-2.0.0', 'timestamped-2.1.0', 'timestamped-2.1.5',
'multi-1.0', 'multi-1.1', 'multi-1.2', 'multi-2.0'
'multi-1.0', 'multi-1.1', 'multi-1.2', 'multi-2.0',
'missing_variant_requires-1'
])


Expand Down
10 changes: 10 additions & 0 deletions src/rez/tests/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"""
from __future__ import print_function

import rez.exceptions
from rez.vendor.version.requirement import Requirement
from rez.solver import Solver, Cycle, SolverStatus
from rez.config import config
Expand Down Expand Up @@ -214,6 +215,7 @@ def test_07(self):

def test_08(self):
"""Cyclic failures."""

def _test(*pkgs):
s = self._fail(*pkgs)
self.assertTrue(isinstance(s.failure_reason(), Cycle))
Expand Down Expand Up @@ -248,6 +250,14 @@ def test_11_variant_splitting(self):
"test_variant_split_mid2-2.0[0]",
"test_variant_split_start-1.0[1]"])

def test_12_missing_variant_requires(self):
config.override("error_on_missing_variant_requires", True)
with self.assertRaises(rez.exceptions.PackageFamilyNotFoundError):
self._solve(["missing_variant_requires"], [])

config.override("error_on_missing_variant_requires", False)
self._solve(["missing_variant_requires"], ["nada[]", "missing_variant_requires-1[1]"])


if __name__ == '__main__':
unittest.main()
Loading