def test_apply_extension_experimental_with_environment(emitter, monkeypatch): monkeypatch.setenv("SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS", "1") yaml_data = { "base": "core22", "apps": { "fake-command": { "command": "bin/fake-command", "extensions": ["fake-extension-experimental"], } }, "parts": { "fake-part": { "source": ".", "plugin": "dump", "after": ["fake-extension-extra/fake-part", "fake-extension/fake-part"], }, }, } # Should not raise. extensions.apply_extensions(yaml_data, arch="amd64", target_arch="amd64") emitter.assert_progress( "*EXPERIMENTAL* extension 'fake-extension-experimental' enabled", permanent=True, )
def apply_yaml(yaml_data: Dict[str, Any]) -> Dict[str, Any]: """Apply Snapcraft logic to yaml_data.""" # validate project grammar GrammarAwareProject.validate_grammar(yaml_data) # Special Snapcraft Part core_part = { k: yaml_data.pop(k) for k in _CORE_PART_KEYS if k in yaml_data } if core_part: core_part["plugin"] = "nil" yaml_data["parts"][_CORE_PART_NAME] = core_part # TODO: support for target_arch arch = _get_arch() yaml_data = extensions.apply_extensions(yaml_data, arch=arch, target_arch=arch) if "parts" in yaml_data: yaml_data["parts"] = grammar.process_parts( parts_yaml_data=yaml_data["parts"], arch=arch, target_arch=arch) return yaml_data
def test_apply_extension_experimental(): yaml_data = { "base": "core22", "apps": { "fake-command": { "command": "bin/fake-command", "extensions": ["fake-extension-experimental"], } }, } with pytest.raises(errors.ExtensionError) as raised: extensions.apply_extensions(yaml_data, arch="amd64", target_arch="amd64") assert ( str(raised.value) == "Extension is experimental: 'fake-extension-experimental'" ) assert raised.value.docs_url == "https://snapcraft.io/docs/supported-extensions"
def test_apply_extension_wrong_base(): yaml_data = { "base": "core20", "apps": { "fake-command": { "command": "bin/fake-command", "extensions": ["fake-extension"], } }, } with pytest.raises(errors.ExtensionError) as raised: extensions.apply_extensions(yaml_data, arch="amd64", target_arch="amd64") assert ( str(raised.value) == "Extension 'fake-extension' does not support base: 'core20'" )
def test_apply_extension_invalid_parts(): # This is a Snapcraft developer error. yaml_data = { "base": "core22", "apps": { "fake-command": { "command": "bin/fake-command", "extensions": ["fake-extension-invalid-parts"], } }, } with pytest.raises(ValueError) as raised: extensions.apply_extensions(yaml_data, arch="amd64", target_arch="amd64") assert str(raised.value) == ( "Extension has invalid part names: ['fake-part', 'fake-part-2']. " "Format is <extension-name>/<part-name>" )
def run(self, parsed_args): snap_project = get_snap_project() yaml_data = process_yaml(snap_project.project_file) expanded_yaml_data = extensions.apply_extensions( yaml_data, arch=get_host_architecture(), target_arch=get_host_architecture(), ) Project.unmarshal(expanded_yaml_data) emit.message( yaml.safe_dump(expanded_yaml_data, indent=4, sort_keys=False))
def test_apply_multiple_extensions(): yaml_data = { "name": "fake-snap", "summary": "fake summary", "description": "fake description", "base": "core22", "apps": { "fake-command": { "command": "bin/fake-command", "plugs": ["my-fake-plug"], "extensions": ["fake-extension", "fake-extension-extra"], } }, "parts": {"fake-part": {"source": ".", "plugin": "dump"}}, } assert extensions.apply_extensions( yaml_data, arch="amd64", target_arch="amd64" ) == { "name": "fake-snap", "summary": "fake summary", "description": "fake description", "base": "core22", "grade": "fake-grade", "apps": { "fake-command": { "command": "bin/fake-command", "plugs": ["fake-plug", "fake-plug-extra", "my-fake-plug"], } }, "parts": { "fake-part": { "source": ".", "plugin": "dump", "after": ["fake-extension-extra/fake-part", "fake-extension/fake-part"], }, "fake-extension/fake-part": { "plugin": "nil", "after": ["fake-extension-extra/fake-part"], }, "fake-extension-extra/fake-part": {"plugin": "nil"}, }, }
def apply_yaml(yaml_data: Dict[str, Any], build_on: str, build_for: str) -> Dict[str, Any]: """Apply Snapcraft logic to yaml_data. Extensions are applied and advanced grammar is processed. The architectures data is reduced to architectures in the current build plan. :param yaml_data: The project YAML data. :param build_for: Target architecture the snap project will be built to. """ # validate project grammar GrammarAwareProject.validate_grammar(yaml_data) # Special Snapcraft Part core_part = { k: yaml_data.pop(k) for k in _CORE_PART_KEYS if k in yaml_data } if core_part: core_part["plugin"] = "nil" yaml_data["parts"][_CORE_PART_NAME] = core_part yaml_data = extensions.apply_extensions(yaml_data, arch=build_on, target_arch=build_for) if "parts" in yaml_data: yaml_data["parts"] = grammar.process_parts( parts_yaml_data=yaml_data["parts"], arch=build_on, target_arch=build_for) # replace all architectures with the architectures in the current build plan yaml_data["architectures"] = [ Architecture(build_on=build_on, build_for=build_for) ] return yaml_data