Skip to content

Commit

Permalink
feat: add Snapcraft-specific Poetry plugin
Browse files Browse the repository at this point in the history
The plugin has the same behavior and restrictions as the Python plugin with
regards to base-dependent behavior, symlink handling, etc.

Therefore, this common behavior is extracted into a new "python_common" module,
used by both plugins. This approach is also taken for the reference docs - the
requirement of staging a Python interpreter (or not) is the same for both
plugins.

Enabled for core22 and core24.

Fixes #5025
  • Loading branch information
tigarmo committed Oct 3, 2024
1 parent 932f9e4 commit 6d056a6
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 6 deletions.
3 changes: 0 additions & 3 deletions snapcraft/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ def _register_default_plugins(self) -> None:
"""Register per application plugins when initializing."""
super()._register_default_plugins()

# poetry plugin needs integration work, see #5025
craft_parts.plugins.unregister("poetry")

if self._known_core24:
# dotnet is disabled for core24 and newer because it is pending a rewrite
craft_parts.plugins.unregister("dotnet")
Expand Down
55 changes: 55 additions & 0 deletions snapcraft/parts/plugins/python_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2023-2024 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Common functions for Python-based Snapcraft plugins."""
import logging
from pathlib import Path

from craft_parts import StepInfo

logger = logging.getLogger(__name__)


def post_prime(step_info: StepInfo) -> None:
"""Perform Python-specific actions right before packing."""
base = step_info.project_base

if base in ("core20", "core22"):
# Only fix pyvenv.cfg on core24+ snaps
return

root_path: Path = step_info.prime_dir

pyvenv = root_path / "pyvenv.cfg"
if not pyvenv.is_file():
return

snap_path = Path(f"/snap/{step_info.project_name}/current")
new_home = f"home = {snap_path}"

candidates = (
step_info.part_install_dir,
step_info.stage_dir,
)

old_contents = contents = pyvenv.read_text()
for candidate in candidates:
old_home = f"home = {candidate}"
contents = contents.replace(old_home, new_home)

if old_contents != contents:
logger.debug("Updating pyvenv.cfg to:\n%s", contents)
pyvenv.write_text(contents)
2 changes: 1 addition & 1 deletion snapcraft/services/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def post_prime(self, step_info: StepInfo) -> bool:
plugin_name = project.parts[part_name]["plugin"]

# Handle plugin-specific prime fixes
if plugin_name == "python":
if plugin_name in ("python", "poetry"):
plugins.PythonPlugin.post_prime(step_info)

# Handle patch-elf
Expand Down
14 changes: 14 additions & 0 deletions tests/spread/core24/python-hello/poetry/snap/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: python-hello-poetry
version: "1.0"
summary: simple python application
description: build a python application using core24
base: core24
confinement: strict

apps:
python-hello-strict:
command: bin/hello
parts:
hello:
plugin: poetry
source: src
18 changes: 18 additions & 0 deletions tests/spread/core24/python-hello/poetry/src/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[tool.poetry]
name = "hello"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.10"
black = "^24.8.0"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry.scripts]
hello = "hello:main"
1 change: 1 addition & 0 deletions tests/spread/core24/python-hello/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ systems:
environment:
PARAM/strict: ""
PARAM/classic: "--classic"
PARAM/poetry: ""

restore: |
cd ./"${SPREAD_VARIANT}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: python-hello
version: "1.0"
summary: simple python application
description: build a python application using core22
base: core22
confinement: strict

apps:
python-hello:
command: bin/hello

parts:
hello:
plugin: poetry
source: src
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def main():
print("hello world")
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[tool.poetry]
name = "hello"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.10"
black = "^24.8.0"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry.scripts]
hello = "hello:main"
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ environment:
SNAP/colcon_ros2_wrapper: colcon-ros2-wrapper
SNAP/flutter: flutter-hello
SNAP/python: python-hello
SNAP/poetry: poetry-hello
SNAP/qmake: qmake-hello
SNAP/maven: maven-hello
SNAP/dotnet: dotnet-hello
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/parts/plugins/test_python_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import pytest
from craft_parts import Part, PartInfo, ProjectInfo, Step, StepInfo, errors

from snapcraft.parts.plugins import PythonPlugin
from snapcraft.parts.plugins import PythonPlugin, python_common


@pytest.fixture
Expand Down Expand Up @@ -224,7 +224,7 @@ def test_fix_pyvenv(new_dir, home_attr):

step_info = StepInfo(part_info, Step.PRIME)

PythonPlugin.post_prime(step_info)
python_common.post_prime(step_info)

new_contents = pyvenv.read_text()
assert "home = /snap/test-snap/current/usr/bin" in new_contents

0 comments on commit 6d056a6

Please sign in to comment.