Skip to content

Commit

Permalink
extensions: plugin aware part_snippet values
Browse files Browse the repository at this point in the history
Extend the API to take a plugin_name, for legacy do the same, but as
an optional method in the base class.

Signed-off-by: Sergio Schvezov <sergio.schvezov@canonical.com>
  • Loading branch information
sergiusens committed Jul 12, 2023
1 parent 7c80a05 commit 08ec500
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 20 deletions.
9 changes: 6 additions & 3 deletions snapcraft/extensions/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,13 @@ def _apply_extension(
app_definition.get(property_name), property_value
)

# Next, apply the part-specific components
part_extension = extension.get_part_snippet()
# Next, apply the part-specific components, this can be plugin
# aware.
parts = yaml_data["parts"]
for _part_name, part_definition in parts.items():
for _, part_definition in parts.items():
part_extension = extension.get_part_snippet(
plugin_name=part_definition["plugin"]
)
for property_name, property_value in part_extension.items():
part_definition[property_name] = _apply_extension_property(
part_definition.get(property_name), property_value
Expand Down
2 changes: 1 addition & 1 deletion snapcraft/extensions/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def get_app_snippet(self) -> Dict[str, Any]:
"""Return the app snippet to apply."""

@abc.abstractmethod
def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
"""Return the part snippet to apply to existing parts."""

@abc.abstractmethod
Expand Down
2 changes: 1 addition & 1 deletion snapcraft/extensions/gnome.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def get_root_snippet(self) -> Dict[str, Any]:
}

@overrides
def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
sdk_snap = self.gnome_snaps.sdk

return {
Expand Down
2 changes: 1 addition & 1 deletion snapcraft/extensions/kde_neon.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def get_root_snippet(self) -> Dict[str, Any]:
}

@overrides
def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
sdk_snap = self.kde_snaps.sdk
cmake_args = self.ext_info.cmake_args

Expand Down
2 changes: 1 addition & 1 deletion snapcraft/extensions/ros2_humble.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def get_app_snippet(self) -> Dict[str, Any]:
}

@overrides
def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
return {
"build-environment": [
{"ROS_VERSION": self.ROS_VERSION},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None:
self.part_snippet = dict() # type: Dict[str, Any]
self.parts = dict() # type: Dict[str, Any]

def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
"""Return the part snippet to apply to a part."""
return self.part_snippet

def _sanity_check(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None:
base = yaml_data.get("base")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,13 @@ def _apply_extension(
app_definition.get(property_name), property_value
)

# Next, apply the part-specific components
part_extension = extension.part_snippet
# Next, apply the part-specific components, this can be plugin
# aware.
parts = yaml_data["parts"]
for part_name, part_definition in parts.items():
for _, part_definition in parts.items():
part_extension = extension.get_part_snippet(
plugin_name=part_definition["plugin"]
)
for property_name, property_value in part_extension.items():
part_definition[property_name] = _apply_extension_property(
part_definition.get(property_name), property_value
Expand Down
89 changes: 88 additions & 1 deletion tests/legacy/unit/project_loader/extensions/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import textwrap
from typing import Tuple
from typing import Any, Dict, Tuple

from overrides import overrides
from testtools.matchers import Contains, Equals, Not

import snapcraft_legacy.yaml_utils.errors
Expand All @@ -43,6 +44,7 @@ def setUp(self):
self.useFixture(_daemon_extension_fixture())
self.useFixture(_adopt_info_extension_fixture())
self.useFixture(_invalid_extension_fixture())
self.useFixture(_plugin_aware_part_snippet_extension_fixture())


class BasicExtensionTest(ExtensionTestBase):
Expand Down Expand Up @@ -332,6 +334,61 @@ def test_merge_environment(self):

self.run_test()

def test_plugin_aware_part_snippet1(self):
self.set_attributes(
{
"app_definition": textwrap.dedent(
"""\
command: echo 'hello'
extensions: [pluginextension]
"""
),
"expected_app_definition": {
"command": "echo 'hello'",
},
"part_definition": textwrap.dedent(
"""\
plugin: catkin
"""
),
"expected_part_definition": {
"plugin": "catkin",
"prime": [],
"stage": [],
},
}
)

self.run_test()

def test_plugin_aware_part_snippet2(self):
self.set_attributes(
{
"app_definition": textwrap.dedent(
"""\
command: echo 'hello'
extensions: [pluginextension]
"""
),
"expected_app_definition": {
"command": "echo 'hello'",
},
"part_definition": textwrap.dedent(
"""\
plugin: nil
"""
),
"expected_part_definition": {
"plugin": "nil",
"build-environment": [{"FOO": "bar"}],
"prime": [],
"stage": [],
},
}
)

self.run_test()

def test_merge_build_environment(self):
self.set_attributes(
{
Expand Down Expand Up @@ -831,6 +888,36 @@ def __init__(self, extension_name, yaml_data):
return fixture_setup.FakeExtension("buildenvironment2", ExtensionImpl)


def _plugin_aware_part_snippet_extension_fixture():
class ExtensionImpl(Extension):
@staticmethod
def get_supported_bases() -> Tuple[str, ...]:
return ("core20",)

@staticmethod
def get_supported_confinement() -> Tuple[str, ...]:
return ("strict",)

def __init__(self, extension_name, yaml_data):
super().__init__(extension_name=extension_name, yaml_data=yaml_data)
self.root_snippet = {}
self.app_snippet = {}
self.part_snippet = {
"build-environment": [
{"FOO": "bar"},
],
}
self.parts = {}

@overrides
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
if plugin_name == "catkin":
return {}
return self.part_snippet

return fixture_setup.FakeExtension("pluginextension", ExtensionImpl)


def _plug_extension_fixture():
class ExtensionImpl(Extension):
@staticmethod
Expand Down
13 changes: 8 additions & 5 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ def get_root_snippet(self) -> Dict[str, Any]:
def get_app_snippet(self) -> Dict[str, Any]:
return {"plugs": ["fake-plug"]}

def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
if plugin_name == "catkin":
return {}

return {"after": ["fake-extension/fake-part"]}

def get_parts_snippet(self) -> Dict[str, Any]:
Expand Down Expand Up @@ -122,7 +125,7 @@ def get_root_snippet(self) -> Dict[str, Any]:
def get_app_snippet(self) -> Dict[str, Any]:
return {"plugs": ["fake-plug", "fake-plug-extra"]}

def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
return {"after": ["fake-extension-extra/fake-part"]}

def get_parts_snippet(self) -> Dict[str, Any]:
Expand Down Expand Up @@ -156,7 +159,7 @@ def get_root_snippet(self) -> Dict[str, Any]:
def get_app_snippet(self) -> Dict[str, Any]:
return {"plugs": ["fake-plug"]}

def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
return {"after": ["fake-extension/fake-part"]}

def get_parts_snippet(self) -> Dict[str, Any]:
Expand Down Expand Up @@ -192,7 +195,7 @@ def get_root_snippet(self) -> Dict[str, Any]:
def get_app_snippet(self) -> Dict[str, Any]:
return {}

def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
return {}

def get_parts_snippet(self) -> Dict[str, Any]:
Expand Down Expand Up @@ -228,7 +231,7 @@ def get_root_snippet(self) -> Dict[str, Any]:
def get_app_snippet(self) -> Dict[str, Any]:
return {"plugs": ["fake-plug", "fake-plug-extra"]}

def get_part_snippet(self) -> Dict[str, Any]:
def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]:
return {"after": ["fake-extension-extra/fake-part"]}

def get_parts_snippet(self) -> Dict[str, Any]:
Expand Down
46 changes: 46 additions & 0 deletions tests/unit/extensions/test_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,52 @@ def test_apply_extension():
}


@pytest.mark.usefixtures("fake_extension")
def test_apply_extension_plugin_dependent():
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"],
}
},
"parts": {
"fake-part": {"source": ".", "plugin": "dump"},
"ros-untouched": {"source": "ros", "plugin": "catkin"},
},
}

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", "my-fake-plug"],
}
},
"parts": {
"fake-part": {
"source": ".",
"plugin": "dump",
"after": ["fake-extension/fake-part"],
},
"ros-untouched": {"source": "ros", "plugin": "catkin"},
"fake-extension/fake-part": {"plugin": "nil"},
},
}


@pytest.mark.usefixtures("fake_extension")
@pytest.mark.usefixtures("fake_extension_extra")
def test_apply_multiple_extensions():
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/extensions/test_gnome.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def test_get_part_snippet_latest_edge(

@staticmethod
def assert_get_part_snippet(gnome_instance):
assert gnome_instance.get_part_snippet() == {
assert gnome_instance.get_part_snippet(plugin_name="autotools") == {
"build-environment": [
{"PATH": "/snap/gnome-42-2204-sdk/current/usr/bin${PATH:+:$PATH}"},
{
Expand Down Expand Up @@ -254,7 +254,7 @@ def assert_get_part_snippet(gnome_instance):


def test_get_part_snippet_with_external_sdk(gnome_extension_with_build_snap):
assert gnome_extension_with_build_snap.get_part_snippet() == {
assert gnome_extension_with_build_snap.get_part_snippet(plugin_name="meson") == {
"build-environment": [
{"PATH": "/snap/gnome-44-2204-sdk/current/usr/bin${PATH:+:$PATH}"},
{
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/extensions/test_kde_neon.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def test_get_part_snippet_latest_edge(

@staticmethod
def assert_get_part_snippet(kde_neon_instance):
assert kde_neon_instance.get_part_snippet() == {
assert kde_neon_instance.get_part_snippet(plugin_name="cmake") == {
"build-environment": [
{
"PATH": (
Expand All @@ -193,7 +193,7 @@ def assert_get_part_snippet(kde_neon_instance):


def test_get_part_snippet_with_external_sdk(kde_neon_extension_with_build_snap):
assert kde_neon_extension_with_build_snap.get_part_snippet() == {
assert kde_neon_extension_with_build_snap.get_part_snippet(plugin_name="cmake") == {
"build-environment": [
{
"PATH": (
Expand Down

0 comments on commit 08ec500

Please sign in to comment.