From f54690e5f75200b429a850bee42e12b42f646bc5 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Thu, 18 Aug 2022 23:47:00 -0700 Subject: [PATCH 1/5] Python: add bindings for Group.arches --- libcomps/src/python/src/pycomps_groups.c | 14 ++++++++++++++ libcomps/src/python/src/pycomps_groups.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/libcomps/src/python/src/pycomps_groups.c b/libcomps/src/python/src/pycomps_groups.c index 3dce9c1..237f29d 100644 --- a/libcomps/src/python/src/pycomps_groups.c +++ b/libcomps/src/python/src/pycomps_groups.c @@ -18,6 +18,7 @@ */ #include "pycomps_groups.h" +#include "pycomps_mdict.h" #include "libcomps/comps_set.h" PyObject* PyCOMPSGroup_union(PyObject *self, PyObject *other) { @@ -693,6 +694,7 @@ PyTypeObject PyCOMPS_PacksType = { void PyCOMPSPack_dealloc(PyCOMPS_Package *self) { + Py_XDECREF(self->p_arches); COMPS_OBJECT_DESTROY(self->c_obj); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -707,6 +709,7 @@ PyObject* PyCOMPSPack_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self = (PyCOMPS_Package*) type->tp_alloc(type, 0); if (self != NULL) { self->c_obj = COMPS_OBJECT_CREATE(COMPS_DocGroupPackage, NULL); + self->p_arches = NULL; } return (PyObject*) self; } @@ -759,6 +762,13 @@ __COMPS_NUMPROP_GETSET_CLOSURE(COMPS_DocGroupPackage) DocGroupPkg_BAOClosure = { .set_f = &comps_docpackage_set_basearchonly, }; +__COMPS_LIST_GETSET_CLOSURE(COMPS_DocGroupPackage) DocGroupPkg_ArchesClosure = { + .get_f = &comps_docpackage_arches, + .set_f = &comps_docpackage_set_arches, + .p_offset = offsetof(PyCOMPS_Package, p_arches), + .type = &PyCOMPS_StrSeqType, +}; + PyDoc_STRVAR(PyCOMPS_package_type__doc__, "package type which could be one of following:\n\n" "* :py:const:`libcomps.PACKAGE_TYPE_DEFAULT`\n" @@ -784,6 +794,10 @@ PyGetSetDef pack_getset[] = { (getter)__PyCOMPS_get_boolattr, (setter)__PyCOMPS_set_boolattr, "Package basearchonly attribute", (void*)&DocGroupPkg_BAOClosure}, + {"arches", + (getter)__PyCOMPS_get_ids, (setter)__PyCOMPS_set_ids, + ":py:class:`libcomps.StrSeq` of package architectures", + (void*)&DocGroupPkg_ArchesClosure}, {NULL} /* Sentinel */ }; diff --git a/libcomps/src/python/src/pycomps_groups.h b/libcomps/src/python/src/pycomps_groups.h index 9c38fed..3ca4454 100644 --- a/libcomps/src/python/src/pycomps_groups.h +++ b/libcomps/src/python/src/pycomps_groups.h @@ -42,6 +42,7 @@ typedef struct { typedef struct { PyObject_HEAD COMPS_DocGroupPackage * c_obj; + PyObject *p_arches; } PyCOMPS_Package; __H_COMPS_STRPROP_GETSET_CLOSURE(COMPS_DocGroup) /*pycomps_utils.h macro*/ @@ -51,6 +52,7 @@ __H_COMPS_DICT_GETSET_CLOSURE(COMPS_DocGroup) /*pycomps_utils.h macro*/ __H_COMPS_STRPROP_GETSET_CLOSURE(COMPS_DocGroupPackage) /*pycomps_utils.h macro*/ __H_COMPS_NUMPROP_GETSET_CLOSURE(COMPS_DocGroupPackage) /*pycomps_utils.h macro*/ +__H_COMPS_LIST_GETSET_CLOSURE(COMPS_DocGroupPackage) /*pycomps_utils.h macro*/ COMPS_ObjList* comps_groups_union(COMPS_ObjList *groups1, COMPS_ObjList *groups2); From eba5ddde863a8e275263567c8eff5a916a618e15 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Sun, 21 Aug 2022 20:52:03 -0700 Subject: [PATCH 2/5] Python: add get/set implementations for arches A few differences in the behavior may be better solved with a separate getter/setter methods. --- libcomps/src/python/src/pycomps_groups.c | 2 +- libcomps/src/python/src/pycomps_utils.c | 53 ++++++++++++++++++++++++ libcomps/src/python/src/pycomps_utils.h | 3 ++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/libcomps/src/python/src/pycomps_groups.c b/libcomps/src/python/src/pycomps_groups.c index 237f29d..6008f5a 100644 --- a/libcomps/src/python/src/pycomps_groups.c +++ b/libcomps/src/python/src/pycomps_groups.c @@ -795,7 +795,7 @@ PyGetSetDef pack_getset[] = { "Package basearchonly attribute", (void*)&DocGroupPkg_BAOClosure}, {"arches", - (getter)__PyCOMPS_get_ids, (setter)__PyCOMPS_set_ids, + (getter)__PyCOMPS_get_arches, (setter)__PyCOMPS_set_arches, ":py:class:`libcomps.StrSeq` of package architectures", (void*)&DocGroupPkg_ArchesClosure}, {NULL} /* Sentinel */ diff --git a/libcomps/src/python/src/pycomps_utils.c b/libcomps/src/python/src/pycomps_utils.c index 5935897..8a155b9 100644 --- a/libcomps/src/python/src/pycomps_utils.c +++ b/libcomps/src/python/src/pycomps_utils.c @@ -227,6 +227,59 @@ int __PyCOMPS_set_ids(PyObject *self, PyObject *value, void *closure) { #undef _closure_ } +PyObject* __PyCOMPS_get_arches(PyObject *self, void *closure) { + #define _closure_ ((__PyCOMPS_ListGetSetClosure*)closure) + + PyCOMPS_Sequence *ret = (PyCOMPS_Sequence*)GET_FROM(self, _closure_->p_offset); + COMPS_Object * c_obj; + COMPS_ObjList * list; + + if (!ret) { + c_obj = ((PyCompsObject*)self)->c_obj; + list = (COMPS_ObjList*) + comps_object_incref((COMPS_Object*)_closure_->get_f(c_obj)); + if (list == NULL) { + Py_RETURN_NONE; + } + + ret = (PyCOMPS_Sequence*)_closure_->type->tp_new(_closure_->type, + NULL, NULL); + _closure_->type->tp_init((PyObject*)ret, NULL, NULL); + COMPS_OBJECT_DESTROY(ret->list); + ret->list = list; + } else { + Py_INCREF(ret); + } + return (PyObject*)ret; + #undef _closure_ +} + +int __PyCOMPS_set_arches(PyObject *self, PyObject *value, void *closure) { + #define _closure_ ((__PyCOMPS_ListGetSetClosure*)closure) + PyCOMPS_Sequence *pobj; + COMPS_Object * c_obj; + (void) closure; + (void) self; + + if (!value) { + PyErr_SetString(PyExc_TypeError, "Cannot delete attribute arches"); + return -1; + } + if (value->ob_type != _closure_->type) { + PyErr_Format(PyExc_TypeError, "Not %s instance",_closure_->type->tp_name); + return -1; + } + + c_obj = ((PyCompsObject*)self)->c_obj; + _closure_->set_f(c_obj, (COMPS_ObjList *) + COMPS_OBJECT_INCREF(((PyCOMPS_Sequence*)value)->list)); + pobj = (PyCOMPS_Sequence*)GET_FROM(self, _closure_->p_offset); + Py_XDECREF(pobj); + SET_TO(self, _closure_->p_offset, pobj); + return 0; + #undef _closure_ +} + PyObject* __PyCOMPS_get_dict(PyObject *self, void *closure) { #define _closure_ ((__PyCOMPS_DictGetSetClosure*)closure) diff --git a/libcomps/src/python/src/pycomps_utils.h b/libcomps/src/python/src/pycomps_utils.h index ba9bc2f..f4d2ba8 100644 --- a/libcomps/src/python/src/pycomps_utils.h +++ b/libcomps/src/python/src/pycomps_utils.h @@ -108,6 +108,9 @@ typedef struct {\ PyObject* __PyCOMPS_get_ids(PyObject *self, void *closure); int __PyCOMPS_set_ids(PyObject *self, PyObject *value, void *closure); +PyObject* __PyCOMPS_get_arches(PyObject *self, void *closure); +int __PyCOMPS_set_arches(PyObject *self, PyObject *value, void *closure); + PyObject* __PyCOMPS_get_dict(PyObject *self, void *closure); int __PyCOMPS_set_dict(PyObject *self, PyObject *value, void *closure); From c9a3145b3131e7b846fd25523d5ff6cceb454533 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Thu, 18 Aug 2022 23:53:12 -0700 Subject: [PATCH 3/5] Fix libcomps.Group.packages_match(name=...) lookup The default for an unset `type` was wrong and did not allow to find any packages without explicitly passing another `type` value. --- libcomps/src/python/src/pycomps_groups.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcomps/src/python/src/pycomps_groups.c b/libcomps/src/python/src/pycomps_groups.c index 6008f5a..49eea08 100644 --- a/libcomps/src/python/src/pycomps_groups.c +++ b/libcomps/src/python/src/pycomps_groups.c @@ -439,7 +439,7 @@ char __pycomps_pkg_type_check(PyObject* pobj, void *cobj) { PyObject* PyCOMPSGroup_packages_match(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *ret; - int type=-1; + int type=COMPS_PACKAGE_UNKNOWN; char *name = NULL; char *keywords[] = {"name", "type", NULL}; COMPS_ObjList * list; From 6f9ef2c39c103f7abaf12cd8117a6b234f5e21e8 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Sun, 21 Aug 2022 20:25:11 -0700 Subject: [PATCH 4/5] Fix crash when comparing Sequence with incompatible type --- libcomps/src/python/src/pycomps_sequence.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libcomps/src/python/src/pycomps_sequence.c b/libcomps/src/python/src/pycomps_sequence.c index 9b42341..e2e05d1 100644 --- a/libcomps/src/python/src/pycomps_sequence.c +++ b/libcomps/src/python/src/pycomps_sequence.c @@ -565,6 +565,14 @@ PyObject* PyCOMPSSeq_str(PyObject *self) { PyObject* PyCOMPSSeq_cmp(PyObject *self, PyObject *other, int op) { char res; + + if (!PyObject_IsInstance(other, (PyObject *) &PyCOMPS_SeqType)) { + PyErr_Format(PyExc_TypeError, "Cannot compare %s with %s", + Py_TYPE(other)->tp_name, + Py_TYPE(self)->tp_name); + return NULL; + } + res = COMPS_OBJECT_CMP(((PyCOMPS_Sequence*)self)->list, ((PyCOMPS_Sequence*)other)->list); if (op == Py_EQ && res) { From 6c3f02b82a3bac0d6bf8ef288660915caf1943ae Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Sun, 21 Aug 2022 20:54:23 -0700 Subject: [PATCH 5/5] Python: test libcomps.Package.arches --- libcomps/src/python/tests/__test.py | 14 ++++++++ libcomps/src/python/tests/test_libcomps.py | 41 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/libcomps/src/python/tests/__test.py b/libcomps/src/python/tests/__test.py index 4152c7d..5370ff4 100644 --- a/libcomps/src/python/tests/__test.py +++ b/libcomps/src/python/tests/__test.py @@ -610,6 +610,20 @@ def test_attrs(self): self.assertEqual(pkg.name, "kernel-3.2") self.assertEqual(pkg.type, libcomps.PACKAGE_TYPE_MANDATORY) + def test_arch(self): + pkg = libcomps.Package("kernel-3.2", libcomps.PACKAGE_TYPE_MANDATORY) + self.assertFalse(pkg.arches) + arch = libcomps.StrSeq() + arch.append("x86_64") + pkg.arches = arch + utest.assertSequenceEqual(pkg.arches, ["x86_64"]) + + self.comps = libcomps.Comps() + self.comps.groups.append(libcomps.Group("g1", "group1", "group desc", 0, 0, 0, "en")) + self.comps.groups[0].packages.append(pkg) + out = self.comps.xml_str(xml_options={"arch_output": True}) + self.assertIn(" + + + + core + false + true + + package-with-arch + package-without-arch + + + + """) + def find_pkg(group, pkg): + groups = self.comps.groups_match(id=group) + self.assertGreaterEqual(len(groups), 1) + pkgs = groups[0].packages_match(name=pkg) + self.assertGreaterEqual(len(pkgs), 1) + return pkgs[0] + + package = find_pkg("core", "package-without-arch") + self.assertFalse(package.arches) + + package = find_pkg("core", "package-with-arch") + utest.assertSequenceEqual(package.arches, + ["aarch64", "ppc64le", "x86_64"]) + package.arches.clear() + package.arches.append("i686") + utest.assertSequenceEqual(package.arches, ["i686"]) + + options = {"arch_output": True} + self.comps.xml_f(self.tmp_file, xml_options=options) + self.comps.fromxml_str(self.comps.xml_str(xml_options=options)) + + package = find_pkg("core", "package-with-arch") + utest.assertSequenceEqual(package.arches, ["i686"]) + + if __name__ == "__main__": unittest.main(testRunner = utest.MyRunner)