Skip to content

Commit

Permalink
feat(plugins/poetry): add poetry and pip extra args
Browse files Browse the repository at this point in the history
This allows more customisation of the poetry and pip commands for
advanced users.
  • Loading branch information
lengau committed Dec 16, 2024
1 parent 0d9c0a2 commit 7b70112
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 8 deletions.
14 changes: 13 additions & 1 deletion craft_parts/plugins/poetry_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ class PoetryPluginProperties(PluginProperties, frozen=True):
title="Optional dependency groups",
description="optional dependency groups to include when installing.",
)
poetry_export_extra_args: list[str] = pydantic.Field(
default_factory=list,
title="Extra arguments for poetry export",
description="extra arguments to pass to poetry export when creating requirements.txt.",
)
poetry_pip_extra_args: list[str] = pydantic.Field(
default_factory=list,
title="Extra arguments for pip install",
description="extra arguments to pass to pip install installing dependencies.",
)

# part properties required by the plugin
source: str # pyright: ignore[reportGeneralTypeIssues]
Expand Down Expand Up @@ -115,6 +125,7 @@ def _get_poetry_export_commands(self, requirements_path: pathlib.Path) -> list[s
export_command.append(
f"--with={','.join(sorted(self._options.poetry_with))}",
)
export_command.extend(self._options.poetry_export_extra_args)

return [shlex.join(export_command)]

Expand All @@ -128,10 +139,11 @@ def _get_pip_install_commands(self, requirements_path: pathlib.Path) -> list[str
:returns: A list of strings forming the install script.
"""
pip = self._get_pip()
pip_extra_args = shlex.join(self._options.poetry_pip_extra_args)
return [
# These steps need to be separate because poetry export defaults to including
# hashes, which don't work with installing from a directory.
f"{pip} install --requirement={requirements_path}",
f"{pip} install {pip_extra_args} --requirement={requirements_path}",
# All dependencies should be installed through the requirements file made by
# poetry.
f"{pip} install --no-deps .",
Expand Down
13 changes: 13 additions & 0 deletions docs/common/craft-parts/reference/plugins/poetry_plugin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ well as those for :ref:`sources <part-properties-sources>`.
Additionally, this plugin provides the plugin-specific keywords defined in the
following sections.

poetry-export-extra-args:
~~~~~~~~~~~~~~~~~~~~~~~~~
**Type:** list of strings

Extra arguments to pass at the end of the poetry `export command`_.

poetry-pip-extra-args:
~~~~~~~~~~~~~~~~~~~~~~
**Type:** list of strings

Extra arguments to pass to ``pip install`` when installing dependencies.

poetry-with:
~~~~~~~~~~~~
**Type:** list of strings
Expand Down Expand Up @@ -105,4 +117,5 @@ During the build step, the plugin performs the following actions:

.. _Poetry: https://python-poetry.org
.. _dependency groups: https://python-poetry.org/docs/managing-dependencies#dependency-groups
.. _export command: https://python-poetry.org/docs/cli/#export
.. _environment variables to configure Poetry: https://python-poetry.org/docs/configuration/#using-environment-variables
7 changes: 6 additions & 1 deletion tests/integration/plugins/test_poetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ def source_directory(request):

@pytest.fixture
def poetry_part(source_directory):
return {"source": str(source_directory), "plugin": "poetry"}
return {
"source": str(source_directory),
"plugin": "poetry",
"poetry-export-extra-args": ["--without-hashes"],
"poetry-pip-extra-args": ["--no-deps"],
}


@pytest.fixture
Expand Down
23 changes: 17 additions & 6 deletions tests/unit/plugins/test_poetry_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,31 @@ def get_build_commands(


@pytest.mark.parametrize(
("optional_groups", "export_addendum"),
("optional_groups", "poetry_extra_args", "export_addendum"),
[
(set(), ""),
({"dev"}, " --with=dev"),
({"toml", "yaml", "silly-walks"}, " --with=silly-walks,toml,yaml"),
(set(), [], ""),
({"dev"}, [], " --with=dev"),
({"toml", "yaml", "silly-walks"}, [], " --with=silly-walks,toml,yaml"),
(set(), ["--no-binary=:all:"], " --no-binary=:all:"),
],
)
def test_get_build_commands(new_dir, optional_groups, export_addendum):
@pytest.mark.parametrize(
("pip_extra_args", "pip_addendum"),
[
([], ""),
(["--no-binary=:all:"], "--no-binary=:all:"),
(["--pre", "-U"], "--pre -U")
]
)
def test_get_build_commands(new_dir, optional_groups, poetry_extra_args, export_addendum, pip_extra_args, pip_addendum):
info = ProjectInfo(application_name="test", cache_dir=new_dir)
part_info = PartInfo(project_info=info, part=Part("p1", {}))
properties = PoetryPlugin.properties_class.unmarshal(
{
"source": ".",
"poetry-with": optional_groups,
"poetry-export-extra-args": poetry_extra_args,
"poetry-pip-extra-args": pip_extra_args,
}
)

Expand All @@ -160,7 +171,7 @@ def test_get_build_commands(new_dir, optional_groups, export_addendum):
f'PARTS_PYTHON_VENV_INTERP_PATH="{new_dir}/parts/p1/install/bin/${{PARTS_PYTHON_INTERPRETER}}"',
f"poetry export --format=requirements.txt --output={new_dir}/parts/p1/build/requirements.txt --with-credentials"
+ export_addendum,
f"{new_dir}/parts/p1/install/bin/pip install --requirement={new_dir}/parts/p1/build/requirements.txt",
f"{new_dir}/parts/p1/install/bin/pip install {pip_addendum} --requirement={new_dir}/parts/p1/build/requirements.txt",
f"{new_dir}/parts/p1/install/bin/pip install --no-deps .",
f"{new_dir}/parts/p1/install/bin/pip check",
*get_build_commands(new_dir),
Expand Down

0 comments on commit 7b70112

Please sign in to comment.