diff --git a/docs/requirements.txt b/docs/requirements.txt index ee1d7e063c..88dd5313d2 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,7 @@ attrs==23.1.0 catkin-pkg==0.5.2 click==8.1.7 -craft-application==2.6.3 +craft-application==2.7.0 craft-archives==1.1.3 craft-cli==2.5.1 craft-grammar==1.2.0 diff --git a/requirements-devel.txt b/requirements-devel.txt index 5ce8af9759..3fa484f5f2 100644 --- a/requirements-devel.txt +++ b/requirements-devel.txt @@ -11,7 +11,7 @@ click==8.1.7 codespell==2.2.6 colorama==0.4.6 coverage==7.4.4 -craft-application==2.6.3 +craft-application==2.7.0 craft-archives==1.1.3 craft-cli==2.5.1 craft-grammar==1.2.0 diff --git a/requirements.txt b/requirements.txt index 0b722b288c..ac3b5b66b2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ cffi==1.16.0 chardet==5.2.0 charset-normalizer==3.3.2 click==8.1.7 -craft-application==2.6.3 +craft-application==2.7.0 craft-archives==1.1.3 craft-cli==2.5.1 craft-grammar==1.2.0 diff --git a/snapcraft/commands/unimplemented.py b/snapcraft/commands/unimplemented.py index 69d1b164a8..6dddb61d4c 100644 --- a/snapcraft/commands/unimplemented.py +++ b/snapcraft/commands/unimplemented.py @@ -44,6 +44,20 @@ def run(self, parsed_args: argparse.Namespace) -> None: # Fallback to the codepaths for non-core24-code. raise errors.ClassicFallback() + def needs_project( + self, + parsed_args: argparse.Namespace, # noqa: ARG002 (unused argument is for subclasses) + ) -> bool: + """Property to determine if the command needs a project loaded. + + Defaults to `self.always_load_project`. + + :param parsed_args: Parsed arguments for the command. + + :returns: True if the command needs a project loaded, False otherwise. + """ + return self.always_load_project + def run_managed( self, parsed_args: argparse.Namespace, # noqa: ARG002 (the unused argument is for subclasses) diff --git a/snapcraft/models/project.py b/snapcraft/models/project.py index 2981f0b7cc..f990011278 100644 --- a/snapcraft/models/project.py +++ b/snapcraft/models/project.py @@ -44,6 +44,7 @@ from craft_grammar.models import GrammarSingleEntryDictList, GrammarStr, GrammarStrList from craft_providers import bases from pydantic import PrivateAttr, constr +from typing_extensions import override from snapcraft import utils from snapcraft.const import SUPPORTED_ARCHS, SnapArch @@ -602,6 +603,25 @@ class Project(models.Project): provenance: Optional[str] components: Optional[Dict[ProjectName, Component]] + @override + @classmethod + def _providers_base(cls, base: str) -> bases.BaseAlias | None: + """Get a BaseAlias from snapcraft's base. + + :param base: The application-specific base name. + + :returns: The BaseAlias for the base. + + :raises CraftValidationError: If the project's base cannot be determined. + """ + if base == "bare": + return None + + try: + return SNAPCRAFT_BASE_TO_PROVIDER_BASE[base] + except KeyError as err: + raise CraftValidationError(f"Unknown base {base!r}") from err + @pydantic.validator("plugs") @classmethod def _validate_plugs(cls, plugs): diff --git a/tests/unit/models/test_projects.py b/tests/unit/models/test_projects.py index 6fc2aec40f..0eba636ee4 100644 --- a/tests/unit/models/test_projects.py +++ b/tests/unit/models/test_projects.py @@ -24,7 +24,7 @@ from craft_providers.bases import BaseName import snapcraft.models -from snapcraft import const, errors +from snapcraft import const, errors, providers from snapcraft.models import ( MANDATORY_ADOPTABLE_FIELDS, Architecture, @@ -585,6 +585,21 @@ def test_project_build_base_devel_grade_stable_error(self, project_yaml_data): with pytest.raises(errors.ProjectValidationError, match=error): Project.unmarshal(project_yaml_data(build_base="devel", grade="stable")) + @pytest.mark.parametrize( + ("base", "expected_base"), + [("bare", None), *providers.SNAPCRAFT_BASE_TO_PROVIDER_BASE.items()], + ) + def test_provider_base(self, base, expected_base, project_yaml_data): + providers_base = Project._providers_base(base) + + assert providers_base == expected_base + + def test_provider_base_error(self, project_yaml_data): + with pytest.raises(CraftValidationError) as raised: + Project._providers_base("unknown") + + assert "Unknown base 'unknown'" in str(raised.value) + def test_project_global_plugs_warning(self, project_yaml_data, emitter): data = project_yaml_data(plugs={"desktop": None, "desktop-legacy": None}) Project.unmarshal(data)