Skip to content

Commit

Permalink
plugins: add support for pyproject.toml projects (lp:#2008237) (#435)
Browse files Browse the repository at this point in the history
Python projects move to pyproject.toml[0] instead of using setup.py so
add support to craft-parts so snaps can be build using the python
plugin.

[0] https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/
  • Loading branch information
toabctl authored May 3, 2023
1 parent 612c574 commit 438951f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 5 deletions.
6 changes: 4 additions & 2 deletions craft_parts/plugins/python_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class PythonPlugin(Plugin):
It can be used for python projects where you would want to do:
- import python modules with a requirements.txt
- build a python project that has a setup.py
- build a python project that has a setup.py or pyproject.toml
- install packages straight from pip
This plugin uses the common plugin keywords as well as those for "sources".
Expand Down Expand Up @@ -153,7 +153,9 @@ def get_build_commands(self) -> List[str]:
requirements_cmd = f"{pip} install {constraints} -U {requirements}"
build_commands.append(requirements_cmd)

build_commands.append(f"[ -f setup.py ] && {pip} install {constraints} -U .")
build_commands.append(
f"[ -f setup.py ] || [ -f pyproject.toml ] && {pip} install {constraints} -U ."
)

# Now fix shebangs.
script_interpreter = self._get_script_interpreter()
Expand Down
27 changes: 27 additions & 0 deletions tests/integration/plugins/test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ def test_python_plugin(new_dir):
assert primed_script.open().readline().rstrip() == "#!/usr/bin/env python3"


def test_python_plugin_with_pyproject_toml(new_dir):
"""Prime a simple python source."""
source_location = Path(__file__).parent / "test_python_pyproject_toml"

parts_yaml = textwrap.dedent(
f"""\
parts:
foo:
plugin: python
source: {source_location}
"""
)
parts = yaml.safe_load(parts_yaml)

lf = LifecycleManager(
parts, application_name="test_python_pyproject_toml", cache_dir=new_dir
)
actions = lf.plan(Step.PRIME)

with lf.action_executor() as ctx:
ctx.execute(actions)

primed_script = Path(lf.project_info.prime_dir, "bin", "mytestpyprojecttoml")
assert primed_script.exists()
assert primed_script.open().readline().rstrip() == "#!/usr/bin/env python3"


def test_python_plugin_symlink(new_dir):
"""Run in the standard scenario with no overrides."""
parts_yaml = textwrap.dedent(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def main():
print("it works also with pyproject.toml!")
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "plugin_test_pyproject_toml"
description = "My package description"
version = "0.0.1"

[project.scripts]
mytestpyprojecttoml = "mytestpyprojecttoml:main"
6 changes: 3 additions & 3 deletions tests/unit/plugins/test_python_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def test_get_build_commands(plugin, new_dir):
f'"${{PARTS_PYTHON_INTERPRETER}}" -m venv ${{PARTS_PYTHON_VENV_ARGS}} "{new_dir}/parts/p1/install"',
f'PARTS_PYTHON_VENV_INTERP_PATH="{new_dir}/parts/p1/install/bin/${{PARTS_PYTHON_INTERPRETER}}"',
f"{new_dir}/parts/p1/install/bin/pip install -U pip setuptools wheel",
f"[ -f setup.py ] && {new_dir}/parts/p1/install/bin/pip install -U .",
f"[ -f setup.py ] || [ -f pyproject.toml ] && {new_dir}/parts/p1/install/bin/pip install -U .",
] + get_build_commands(new_dir)


Expand All @@ -121,7 +121,7 @@ def test_get_build_commands_with_all_properties(new_dir):
f'PARTS_PYTHON_VENV_INTERP_PATH="{new_dir}/parts/p1/install/bin/${{PARTS_PYTHON_INTERPRETER}}"',
f"{new_dir}/parts/p1/install/bin/pip install -c 'constraints.txt' -U pip 'some-pkg; sys_platform != '\"'\"'win32'\"'\"''",
f"{new_dir}/parts/p1/install/bin/pip install -c 'constraints.txt' -U -r 'requirements.txt'",
f"[ -f setup.py ] && {new_dir}/parts/p1/install/bin/pip install -c 'constraints.txt' -U .",
f"[ -f setup.py ] || [ -f pyproject.toml ] && {new_dir}/parts/p1/install/bin/pip install -c 'constraints.txt' -U .",
] + get_build_commands(new_dir)


Expand Down Expand Up @@ -173,7 +173,7 @@ def test_call_should_remove_symlinks(plugin, new_dir, mocker):
f'"${{PARTS_PYTHON_INTERPRETER}}" -m venv ${{PARTS_PYTHON_VENV_ARGS}} "{new_dir}/parts/p1/install"',
f'PARTS_PYTHON_VENV_INTERP_PATH="{new_dir}/parts/p1/install/bin/${{PARTS_PYTHON_INTERPRETER}}"',
f"{new_dir}/parts/p1/install/bin/pip install -U pip setuptools wheel",
f"[ -f setup.py ] && {new_dir}/parts/p1/install/bin/pip install -U .",
f"[ -f setup.py ] || [ -f pyproject.toml ] && {new_dir}/parts/p1/install/bin/pip install -U .",
f'find "{new_dir}/parts/p1/install" -type f -executable -print0 | xargs -0 \\\n'
f' sed -i "1 s|^#\\!${{PARTS_PYTHON_VENV_INTERP_PATH}}.*$|#!/usr/bin/env ${{PARTS_PYTHON_INTERPRETER}}|"\n',
f"echo Removing python symlinks in {new_dir}/parts/p1/install/bin\n"
Expand Down

0 comments on commit 438951f

Please sign in to comment.