From 2a11a03d264b4fec3e0cbf8febcd8826c0a93cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= Date: Tue, 24 Oct 2023 14:22:08 +0200 Subject: [PATCH 1/4] Enable AdvisoryModule bindings There is a problem in Perl with namespace conflicts. Undefine `get_context` to fix the issue. More general solution would be to use `PERL_NO_SHORT_NAMES` it would fix other potential conflicts however it doesn't compile with it. Some more information is in: https://www.swig.org/Doc4.1/SWIGDocumentation.html#Perl5_nn9 --- bindings/libdnf5/advisory.i | 6 +++--- bindings/libdnf5/shared.i | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/bindings/libdnf5/advisory.i b/bindings/libdnf5/advisory.i index 726844f07..7a74005e1 100644 --- a/bindings/libdnf5/advisory.i +++ b/bindings/libdnf5/advisory.i @@ -25,11 +25,10 @@ } } -// TODO(jkolarik): advisory modules skipped for now - %{ #include "libdnf5/advisory/advisory.hpp" #include "libdnf5/advisory/advisory_package.hpp" + #include "libdnf5/advisory/advisory_module.hpp" #include "libdnf5/advisory/advisory_set.hpp" #include "libdnf5/advisory/advisory_set_iterator.hpp" #include "libdnf5/advisory/advisory_collection.hpp" @@ -47,11 +46,12 @@ %rename(value) libdnf5::advisory::AdvisorySetIterator::operator*(); %include "libdnf5/advisory/advisory_set_iterator.hpp" -%ignore libdnf5::advisory::AdvisoryCollection::get_modules(); +%include "libdnf5/advisory/advisory_module.hpp" %include "libdnf5/advisory/advisory_collection.hpp" %include "libdnf5/advisory/advisory_query.hpp" %include "libdnf5/advisory/advisory_reference.hpp" +%template(VectorAdvisoryModule) std::vector; %template(VectorAdvisoryCollection) std::vector; %template(VectorAdvisoryPackage) std::vector; %template(VectorAdvisoryReference) std::vector; diff --git a/bindings/libdnf5/shared.i b/bindings/libdnf5/shared.i index c2fbf5f89..269257b59 100644 --- a/bindings/libdnf5/shared.i +++ b/bindings/libdnf5/shared.i @@ -12,4 +12,12 @@ // From perl5 - utf8.h: conflicts with fmt/format.h header #undef utf8_to_utf16 + + // Recent versions of Perl (5.8.0) have namespace conflict problems. + // Perl defines a bunch of short macros to make the Perl API function names shorter. + // For example, in /usr/lib64/perl5/CORE/embed.h there is: + // #define get_context Perl_get_context + // We have to undefine that since we don't want our AdvisoryModule::get_context to + // be renamed to Perl_get_context + #undef get_context %} From 694b7476bb93173b46ebfe85e40cab6f055fdb37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= Date: Tue, 24 Oct 2023 07:18:29 +0200 Subject: [PATCH 2/4] Add advisory python API tests For: https://github.com/rpm-software-management/dnf5/issues/213 --- .../python3/libdnf5/advisory/test_advisory.py | 121 +++++++++++++++++- 1 file changed, 117 insertions(+), 4 deletions(-) diff --git a/test/python3/libdnf5/advisory/test_advisory.py b/test/python3/libdnf5/advisory/test_advisory.py index 9eb14dc5f..e5b3896bc 100644 --- a/test/python3/libdnf5/advisory/test_advisory.py +++ b/test/python3/libdnf5/advisory/test_advisory.py @@ -24,9 +24,122 @@ class TestAdvisory(base_test_case.BaseTestCase): def setUp(self): super().setUp() self.add_repo_repomd("repomd-repo1") - - def test_get_name(self): query = libdnf5.advisory.AdvisoryQuery(self.base) query.filter_type("security") - pkg = next(iter(query)) - self.assertEqual(pkg.get_name(), "DNF-2019-1") + self.advisory = next(iter(query)) + + def test_advisory_query(self): + query = libdnf5.advisory.AdvisoryQuery(self.base) + query.filter_name("DNF-2019-1") + self.assertEqual(query.size(), 1) + advisory = next(iter(query)) + self.assertEqual(advisory.get_name(), "DNF-2019-1") + + query = libdnf5.advisory.AdvisoryQuery(self.base) + query.filter_type("bugfix") + self.assertEqual(query.size(), 2) + advisory = next(iter(query)) + self.assertEqual(advisory.get_type(), "bugfix") + + query = libdnf5.advisory.AdvisoryQuery(self.base) + query.filter_reference("1111") + self.assertEqual(query.size(), 1) + advisory = next(iter(query)) + refs = advisory.get_references() + self.assertEqual(len(refs), 1) + self.assertEqual(refs[0].get_id(), "1111") + + query = libdnf5.advisory.AdvisoryQuery(self.base) + query.filter_severity("moderate") + self.assertEqual(query.size(), 1) + advisory = next(iter(query)) + self.assertEqual(advisory.get_severity(), "moderate") + + query = libdnf5.advisory.AdvisoryQuery(self.base) + pkgquery = libdnf5.rpm.PackageQuery(self.base) + query.filter_packages(pkgquery) + self.assertEqual(query.size(), 1) + advisory = next(iter(query)) + self.assertEqual(advisory.get_name(), "DNF-2019-1") + + query = libdnf5.advisory.AdvisoryQuery(self.base) + pkgquery = libdnf5.rpm.PackageQuery(self.base) + pkgs = query.get_advisory_packages_sorted(pkgquery) + self.assertEqual(pkgs.size(), 1) + self.assertEqual(pkgs[0].get_nevra(), "pkg-1.2-3.x86_64") + + def test_advisory(self): + self.assertEqual(self.advisory.get_name(), "DNF-2019-1") + self.assertEqual(self.advisory.get_severity(), "moderate") + self.assertEqual(self.advisory.get_type(), "security") + self.assertEqual(self.advisory.get_buildtime(), 1550849401) + self.assertEqual(self.advisory.get_vendor(), "dnf-testing@redhat.com") + self.assertEqual(self.advisory.get_description(), + "testing advisory 2019") + self.assertEqual(self.advisory.get_title(), "bugfix_A-1.0-1") + self.assertEqual(self.advisory.get_status(), "stable") + self.assertEqual(self.advisory.get_rights(), "") + self.assertEqual(self.advisory.get_message(), "") + self.assertEqual(self.advisory.is_applicable(), True) + + def test_references(self): + refs = self.advisory.get_references() + self.assertEqual(len(refs), 1) + reference = refs[0] + self.assertEqual(reference.get_id(), "1111") + self.assertEqual(reference.get_type(), "cve") + self.assertEqual(reference.get_title(), "CVE-2999") + self.assertEqual(reference.get_url(), "https://foobar/foobarupdate_2") + + def test_collections(self): + cols = self.advisory.get_collections() + self.assertEqual(len(cols), 1) + collection = cols[0] + self.assertEqual(collection.get_advisory_id(), self.advisory.get_id()) + self.assertEqual(collection.get_advisory(), self.advisory) + self.assertEqual(collection.is_applicable(), True) + + def test_advisory_packages(self): + collection = self.advisory.get_collections()[0] + adv_packages = collection.get_packages() + self.assertEqual(len(adv_packages), 2) + adv_package = adv_packages[0] + + self.assertEqual(adv_package.get_advisory_id(), self.advisory.get_id()) + self.assertEqual(adv_package.get_advisory(), self.advisory) + # We can't compare the collections directly because adv_package constructs + # a new instance of the same collection + self.assertEqual(adv_package.get_advisory_collection( + ).get_advisory_id(), self.advisory.get_id()) + + self.assertEqual(adv_package.get_name(), "pkg") + self.assertEqual(adv_package.get_epoch(), "0") + self.assertEqual(adv_package.get_version(), "1.2") + self.assertEqual(adv_package.get_release(), "3") + self.assertEqual(adv_package.get_evr(), "1.2-3") + self.assertEqual(adv_package.get_arch(), "x86_64") + self.assertEqual(adv_package.get_nevra(), "pkg-1.2-3.x86_64") + + self.assertEqual(adv_package.get_reboot_suggested(), True) + self.assertEqual(adv_package.get_restart_suggested(), False) + self.assertEqual(adv_package.get_relogin_suggested(), False) + + def test_advisory_modules(self): + collection = self.advisory.get_collections()[0] + adv_modules = collection.get_modules() + self.assertEqual(len(adv_modules), 2) + adv_module = adv_modules[0] + + self.assertEqual(adv_module.get_advisory_id(), self.advisory.get_id()) + self.assertEqual(adv_module.get_advisory(), self.advisory) + # We can't compare the collections directly because adv_module constructs + # a new instance of the same collection + self.assertEqual(adv_module.get_advisory_collection( + ).get_advisory_id(), self.advisory.get_id()) + + self.assertEqual(adv_module.get_name(), "perl-DBI") + self.assertEqual(adv_module.get_stream(), "master") + self.assertEqual(adv_module.get_version(), "2") + self.assertEqual(adv_module.get_context(), "2a") + self.assertEqual(adv_module.get_arch(), "x86_64") + self.assertEqual(adv_module.get_nsvca(), "perl-DBI:master:2:2a:x86_64") From 030ecf532ef4b4e6c9b759475435c18d08349269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= Date: Tue, 28 Feb 2023 10:40:27 +0100 Subject: [PATCH 3/4] doc: Add python advisory docs --- doc/api/python/libdnf5_advisory.rst | 12 ++++++++++++ doc/api/python/libdnf5_advisory_advisory.rst | 6 ++++++ .../python/libdnf5_advisory_advisory_collection.rst | 6 ++++++ doc/api/python/libdnf5_advisory_advisory_module.rst | 6 ++++++ doc/api/python/libdnf5_advisory_advisory_package.rst | 6 ++++++ doc/api/python/libdnf5_advisory_advisory_query.rst | 6 ++++++ .../python/libdnf5_advisory_advisory_reference.rst | 6 ++++++ doc/api/python/libdnf5_advisory_advisory_set.rst | 6 ++++++ doc/api/python/python.rst | 1 + 9 files changed, 55 insertions(+) create mode 100644 doc/api/python/libdnf5_advisory.rst create mode 100644 doc/api/python/libdnf5_advisory_advisory.rst create mode 100644 doc/api/python/libdnf5_advisory_advisory_collection.rst create mode 100644 doc/api/python/libdnf5_advisory_advisory_module.rst create mode 100644 doc/api/python/libdnf5_advisory_advisory_package.rst create mode 100644 doc/api/python/libdnf5_advisory_advisory_query.rst create mode 100644 doc/api/python/libdnf5_advisory_advisory_reference.rst create mode 100644 doc/api/python/libdnf5_advisory_advisory_set.rst diff --git a/doc/api/python/libdnf5_advisory.rst b/doc/api/python/libdnf5_advisory.rst new file mode 100644 index 000000000..8e7d03259 --- /dev/null +++ b/doc/api/python/libdnf5_advisory.rst @@ -0,0 +1,12 @@ +libdnf5.advisory +================ + + +.. toctree:: + libdnf5_advisory_advisory + libdnf5_advisory_advisory_collection + libdnf5_advisory_advisory_module + libdnf5_advisory_advisory_package + libdnf5_advisory_advisory_query + libdnf5_advisory_advisory_reference + libdnf5_advisory_advisory_set diff --git a/doc/api/python/libdnf5_advisory_advisory.rst b/doc/api/python/libdnf5_advisory_advisory.rst new file mode 100644 index 000000000..b5842dd30 --- /dev/null +++ b/doc/api/python/libdnf5_advisory_advisory.rst @@ -0,0 +1,6 @@ +Advisory +======== + + +.. autoclass:: libdnf5.advisory.Advisory + :members: diff --git a/doc/api/python/libdnf5_advisory_advisory_collection.rst b/doc/api/python/libdnf5_advisory_advisory_collection.rst new file mode 100644 index 000000000..f76830275 --- /dev/null +++ b/doc/api/python/libdnf5_advisory_advisory_collection.rst @@ -0,0 +1,6 @@ +AdvisoryCollection +================== + + +.. autoclass:: libdnf5.advisory.AdvisoryCollection + :members: diff --git a/doc/api/python/libdnf5_advisory_advisory_module.rst b/doc/api/python/libdnf5_advisory_advisory_module.rst new file mode 100644 index 000000000..6a76a0190 --- /dev/null +++ b/doc/api/python/libdnf5_advisory_advisory_module.rst @@ -0,0 +1,6 @@ +AdvisoryModule +============== + + +.. autoclass:: libdnf5.advisory.AdvisoryModule + :members: diff --git a/doc/api/python/libdnf5_advisory_advisory_package.rst b/doc/api/python/libdnf5_advisory_advisory_package.rst new file mode 100644 index 000000000..5bd531be4 --- /dev/null +++ b/doc/api/python/libdnf5_advisory_advisory_package.rst @@ -0,0 +1,6 @@ +AdvisoryPackage +=============== + + +.. autoclass:: libdnf5.advisory.AdvisoryPackage + :members: diff --git a/doc/api/python/libdnf5_advisory_advisory_query.rst b/doc/api/python/libdnf5_advisory_advisory_query.rst new file mode 100644 index 000000000..3f8aa374a --- /dev/null +++ b/doc/api/python/libdnf5_advisory_advisory_query.rst @@ -0,0 +1,6 @@ +AdvisoryQuery +============= + + +.. autoclass:: libdnf5.advisory.AdvisoryQuery + :members: diff --git a/doc/api/python/libdnf5_advisory_advisory_reference.rst b/doc/api/python/libdnf5_advisory_advisory_reference.rst new file mode 100644 index 000000000..3a54c3733 --- /dev/null +++ b/doc/api/python/libdnf5_advisory_advisory_reference.rst @@ -0,0 +1,6 @@ +AdvisoryReference +================= + + +.. autoclass:: libdnf5.advisory.AdvisoryReference + :members: diff --git a/doc/api/python/libdnf5_advisory_advisory_set.rst b/doc/api/python/libdnf5_advisory_advisory_set.rst new file mode 100644 index 000000000..285ea353a --- /dev/null +++ b/doc/api/python/libdnf5_advisory_advisory_set.rst @@ -0,0 +1,6 @@ +AdvisorySet +=========== + + +.. autoclass:: libdnf5.advisory.AdvisorySet + :members: diff --git a/doc/api/python/python.rst b/doc/api/python/python.rst index d356eb116..f092ea4b2 100644 --- a/doc/api/python/python.rst +++ b/doc/api/python/python.rst @@ -4,6 +4,7 @@ Python .. toctree:: + libdnf5_advisory libdnf5_base libdnf5_repo libdnf5_rpm From 0c34c3a1a626544ad6dd183057c91df3ac0b03a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= Date: Tue, 24 Oct 2023 16:23:42 +0200 Subject: [PATCH 4/4] doc: Generate docs for undocummented functions so they at least show up This is alread done in AutoAPI by default (used in readthedocs for python API). --- doc/conf.py.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/conf.py.in b/doc/conf.py.in index 753973f94..570d9a1b1 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -54,6 +54,12 @@ extensions = [ breathe_projects = {'dnf5': '@CMAKE_CURRENT_BINARY_DIR@/xml/'} breathe_default_project = 'dnf5' +# Show undocumented members for both C++ and Python API docs +breathe_default_members = ('members', 'undoc-members') +autodoc_default_options = { + 'undoc-members': True, +} + # The autoapi config is only used doc/setup.py in readthedocs workflow (not by cmake) autoapi_type = 'python' autoapi_dirs = ['@CMAKE_CURRENT_BINARY_DIR@/../bindings/python3/libdnf5', '@CMAKE_CURRENT_BINARY_DIR@/../bindings/python3/libdnf5_cli']