diff --git a/hab/errors.py b/hab/errors.py index 838e1e2..f3cc0dc 100644 --- a/hab/errors.py +++ b/hab/errors.py @@ -22,6 +22,24 @@ class MaxRedirectError(RequirementError): """The maximum number of redirects was reached without resolving successfully.""" +class InvalidAliasError(HabError): + """Raised the requested alias was not found. + + Args: + alias (str): The requested alias name. + cfg (hab.parser.Config): The hab config used to launch the alias. + msg (str, optional): The error message. `str.format` is called on this + passing the kwargs `alias` and `uri`. + """ + + def __init__(self, alias, cfg, msg=None): + self.alias = alias + self.cfg = cfg + if msg is None: + msg = 'The alias "{alias}" is not found for URI "{uri}".' + super().__init__(msg.format(alias=alias, uri=cfg.uri)) + + class InvalidRequirementError(RequirementError): """Raised if unable to resolve a given requirement.""" diff --git a/hab/parsers/config.py b/hab/parsers/config.py index ec94666..6aad2ec 100644 --- a/hab/parsers/config.py +++ b/hab/parsers/config.py @@ -2,7 +2,7 @@ import os from .. import NotSet, utils -from ..errors import HabError +from ..errors import HabError, InvalidAliasError from .hab_base import HabBase from .meta import hab_property @@ -71,7 +71,7 @@ def launch(self, alias_name, args=None, blocking=False, cls=None, **kwargs): """ # Construct the command line arguments to execute if alias_name not in self.aliases: - raise HabError(f'"{alias_name}" is not a valid alias name') + raise InvalidAliasError(alias_name, self) alias = self.aliases[alias_name] # Get the subprocess.Popen like class to use to launch the alias diff --git a/hab/parsers/hab_base.py b/hab/parsers/hab_base.py index 30a24a9..bd412c1 100644 --- a/hab/parsers/hab_base.py +++ b/hab/parsers/hab_base.py @@ -9,7 +9,12 @@ from packaging.version import Version from .. import NotSet, utils -from ..errors import DuplicateJsonError, HabError, ReservedVariableNameError +from ..errors import ( + DuplicateJsonError, + HabError, + InvalidAliasError, + ReservedVariableNameError, +) from ..formatter import Formatter from ..site import MergeDict from ..solvers import Solver @@ -809,7 +814,7 @@ def generate_config_script( # Get the cmd to launch, raising useful errors if invalid if launch not in self.aliases: - raise HabError(f'"{launch}" is not a valid alias name') + raise InvalidAliasError(launch, self) alias = self.aliases.get(launch, {}) try: diff --git a/tests/test_launch.py b/tests/test_launch.py index c6de0cf..351169a 100644 --- a/tests/test_launch.py +++ b/tests/test_launch.py @@ -8,7 +8,7 @@ import pytest from hab import Resolver, Site, utils -from hab.errors import HabError +from hab.errors import HabError, InvalidAliasError class Topen(subprocess.Popen): @@ -115,7 +115,10 @@ def test_pythonw(monkeypatch, resolver): def test_invalid_alias(resolver): cfg = resolver.resolve("app/aliased/mod") - with pytest.raises(HabError, match='"not-a-alias" is not a valid alias name'): + with pytest.raises( + InvalidAliasError, + match='The alias "not-a-alias" is not found for URI "app/aliased/mod".', + ): cfg.launch("not-a-alias") # Remove the "cmd" value to test an invalid configuration diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 0e3e3c3..c543ecd 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -291,7 +291,10 @@ def test_invalid_alias(uncached_resolver, tmpdir, ext): # Check that calling a bad alias name raises a useful error message cfg = uncached_resolver.resolve("not_set/child") - with pytest.raises(errors.HabError, match=r'"bad-alias" is not a valid alias name'): + with pytest.raises( + errors.InvalidAliasError, + match=r'The alias "bad-alias" is not found for URI "not_set/child".', + ): cfg.write_script(str(tmpdir), launch="bad-alias", **kwargs) # Remove the "cmd" value to test an invalid configuration