diff --git a/CHANGELOG.md b/CHANGELOG.md index 710e4c46..090f06e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Internally created executors are now named for improved metrics and debuggability. +- Library no longer has a hard dependency on Python bindings to `rpm`, if RPM-related + functionality is not used. ## [2.9.0] - 2021-07-05 diff --git a/src/pushsource/_impl/backend/broken_rpmlib.py b/src/pushsource/_impl/backend/broken_rpmlib.py new file mode 100644 index 00000000..6fd6b705 --- /dev/null +++ b/src/pushsource/_impl/backend/broken_rpmlib.py @@ -0,0 +1,17 @@ +import six + +# A replacement for kobo.rpmlib to give a decent error message +# when rpm bindings are not available. + +# importer is expected to put a more specific cause here. +CAUSE = RuntimeError("unknown error") + +MESSAGE = "kobo.rpmlib is not available (consider 'pip install rpm-py-installer')" + + +def not_available(*_args, **_kwargs): + six.raise_from(RuntimeError(MESSAGE), CAUSE) + + +get_rpm_header = not_available +get_keys_from_header = not_available diff --git a/src/pushsource/_impl/backend/staged/staged_rpm.py b/src/pushsource/_impl/backend/staged/staged_rpm.py index eb7f0c74..955cbfe5 100644 --- a/src/pushsource/_impl/backend/staged/staged_rpm.py +++ b/src/pushsource/_impl/backend/staged/staged_rpm.py @@ -1,6 +1,14 @@ import logging -import kobo.rpmlib +try: + from kobo import rpmlib +except Exception as ex: # pragma: no cover, pylint: disable=broad-except + # If kobo.rpmlib is unavailable, let's not immediately crash. + # We will hold this exception and re-raise it only if there's an + # attempt to use the related functionality. + from .. import broken_rpmlib as rpmlib + + rpmlib.CAUSE = ex from ...model import RpmPushItem from .staged_base import StagedBaseMixin, handles_type @@ -19,8 +27,8 @@ def __push_item(self, leafdir, _, entry): LOG.warning("Unexpected non-RPM %s (ignored)", entry.path) return None - header = kobo.rpmlib.get_rpm_header(entry.path) - key_id = kobo.rpmlib.get_keys_from_header(header) + header = rpmlib.get_rpm_header(entry.path) + key_id = rpmlib.get_keys_from_header(header) return RpmPushItem( name=entry.name, diff --git a/tests/staged/test_broken_rpmlib.py b/tests/staged/test_broken_rpmlib.py new file mode 100644 index 00000000..9aba47a2 --- /dev/null +++ b/tests/staged/test_broken_rpmlib.py @@ -0,0 +1,15 @@ +import pytest + +from pushsource._impl.backend import broken_rpmlib + + +@pytest.mark.parametrize( + "fn", [broken_rpmlib.get_keys_from_header, broken_rpmlib.get_rpm_header] +) +def test_functions_raise(fn): + """Expected functions are present in broken_rpmlib and raise on use.""" + + with pytest.raises(RuntimeError) as excinfo: + fn("a", "b", "c") + + assert "kobo.rpmlib is not available" in str(excinfo)