diff options
| -rw-r--r-- | debian/changelog | 1 | ||||
| -rw-r--r-- | doc/source/library/apt_pkg.rst | 26 | ||||
| -rw-r--r-- | python/apt_pkgmodule.cc | 1 | ||||
| -rw-r--r-- | python/apt_pkgmodule.h | 1 | ||||
| -rw-r--r-- | python/cache.cc | 153 | ||||
| -rw-r--r-- | tests/test_group.py | 5 |
6 files changed, 160 insertions, 27 deletions
diff --git a/debian/changelog b/debian/changelog index f241e749..275d8cad 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,7 @@ python-apt (0.8.0~exp1) UNRELEASED; urgency=low no progress output * Support (name, arch) tuples in apt_pkg.Cache mappings, wrapping FindPkg() with two string parameters. + * Introduce apt_pkg.Cache.groups and apt_pkg.Cache.group_count -- Julian Andres Klode <jak@debian.org> Tue, 05 Apr 2011 10:33:54 +0200 diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst index 74bba8db..22225aa4 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -95,6 +95,32 @@ Working with the cache A list of all :class:`PackageFile` objects stored in the cache. + .. attribute:: group_count + + The number of groups in the cache. + + .. attribute:: groups + + A sequence of :class:`Group` objects, implemented as a + :class:`GroupList` object. + + .. class:: GroupList + + A simple sequence-like object which only provides a length and + an implementation of ``__getitem__`` for accessing groups at + a certain index. Apart from being iterable, it can be used in + the following ways: + + .. describe:: list[index] + + Get the :class:`Group` object for the group at the position + given by *index* in the GroupList *list*. + + .. describe:: len(list) + + Return the length of the GroupList object *list*. + + .. attribute:: is_multi_arch An attribute determining whether the cache supports multi-arch. diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index e14677b1..0fac664b 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -815,6 +815,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"Package",&PyPackage_Type); // NO __new__() ADDTYPE(Module,"Version",&PyVersion_Type); // NO __new__() ADDTYPE(Module,"Group", &PyGroup_Type); + ADDTYPE(Module,"GroupList", &PyGroupList_Type); /* ============================ cdrom.cc ============================ */ ADDTYPE(Module,"Cdrom",&PyCdrom_Type); /* ========================= configuration.cc ========================= */ diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 0081a1a9..7a04204c 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -71,6 +71,7 @@ extern PyTypeObject PyCacheFile_Type; extern PyTypeObject PyPackageList_Type; extern PyTypeObject PyDescription_Type; extern PyTypeObject PyGroup_Type; +extern PyTypeObject PyGroupList_Type; /* internal */ extern PyTypeObject PyPackage_Type; extern PyTypeObject PyPackageFile_Type; extern PyTypeObject PyDependency_Type; diff --git a/python/cache.cc b/python/cache.cc index cb877eee..a27bf6f5 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -39,13 +39,57 @@ const char *UntranslatedDepTypes[] = }; /*}}}*/ -struct PkgListStruct + +template<typename T> struct IterListStruct { - pkgCache::PkgIterator Iter; + T Iter; unsigned long LastIndex; - PkgListStruct(pkgCache::PkgIterator const &I) : Iter(I), LastIndex(0) {} - PkgListStruct() {abort();}; // G++ Bug.. + IterListStruct(T const &I) : Iter(I), LastIndex(0) {} + IterListStruct() {}; + + bool move(unsigned long Index) { + if (Index < 0 || (unsigned)Index >= Count()) + { + PyErr_SetNone(PyExc_IndexError); + return false; + } + + if ((unsigned)Index < LastIndex) + { + LastIndex = 0; + Iter = Begin(); + } + + while ((unsigned)Index > LastIndex) + { + LastIndex++; + Iter++; + if (Iter.end() == true) + { + PyErr_SetNone(PyExc_IndexError); + return false; + } + } + return true; + } + + virtual unsigned Count() = 0; + virtual T Begin() = 0; + +}; + +struct PkgListStruct : public IterListStruct<pkgCache::PkgIterator> { + unsigned Count() { return Iter.Cache()->HeaderP->PackageCount; } + pkgCache::PkgIterator Begin() { return Iter.Cache()->PkgBegin(); } + + PkgListStruct(pkgCache::PkgIterator const &I) { Iter = I; } +}; + +struct GrpListStruct : public IterListStruct<pkgCache::GrpIterator> { + unsigned Count() { return Iter.Cache()->HeaderP->GroupCount; } + pkgCache::GrpIterator Begin() { return Iter.Cache()->GrpBegin(); } + GrpListStruct(pkgCache::GrpIterator const &I) { Iter = I; } }; struct RDepListStruct @@ -175,6 +219,16 @@ static PyMethodDef PkgCacheMethods[] = {} }; +static PyObject *PkgCacheGetGroupCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return Py_BuildValue("i",Cache->HeaderP->GroupCount); +} + +static PyObject *PkgCacheGetGroups(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return CppPyObject_NEW<GrpListStruct>(Self,&PyGroupList_Type,Cache->GrpBegin()); +} + static PyObject *PkgCacheGetPackages(PyObject *Self, void*) { pkgCache *Cache = GetCpp<pkgCache *>(Self); return CppPyObject_NEW<PkgListStruct>(Self,&PyPackageList_Type,Cache->PkgBegin()); @@ -232,6 +286,9 @@ static PyGetSetDef PkgCacheGetSet[] = { "The number of apt_pkg.Dependency objects stored in the cache."}, {"file_list",PkgCacheGetFileList,0, "A list of apt_pkg.PackageFile objects stored in the cache."}, + {"group_count",PkgCacheGetGroupCount,0, + "The number of apt_pkg.Group objects stored in the cache."}, + {"groups", PkgCacheGetGroups, 0, "A list of Group objects in the cache"}, {"is_multi_arch", PkgCacheGetIsMultiArch, 0, "Whether the cache supports multi-arch."}, {"package_count",PkgCacheGetPackageCount,0, @@ -442,7 +499,7 @@ PyTypeObject PyCacheFile_Type = 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags }; - /*}}}*/ + // Package List Class /*{{{*/ // --------------------------------------------------------------------- static Py_ssize_t PkgListLen(PyObject *Self) @@ -453,29 +510,9 @@ static Py_ssize_t PkgListLen(PyObject *Self) static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index) { PkgListStruct &Self = GetCpp<PkgListStruct>(iSelf); - if (Index < 0 || (unsigned)Index >= Self.Iter.Cache()->HeaderP->PackageCount) - { - PyErr_SetNone(PyExc_IndexError); - return 0; - } - - if ((unsigned)Index < Self.LastIndex) - { - Self.LastIndex = 0; - Self.Iter = Self.Iter.Cache()->PkgBegin(); - } - - while ((unsigned)Index > Self.LastIndex) - { - Self.LastIndex++; - Self.Iter++; - if (Self.Iter.end() == true) - { - PyErr_SetNone(PyExc_IndexError); - return 0; - } - } + if (!Self.move(Index)) + return 0; return CppPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PyPackage_Type, Self.Iter); } @@ -525,6 +562,68 @@ PyTypeObject PyPackageList_Type = CppClear<PkgListStruct>, // tp_clear }; +/* The same for groups */ +static Py_ssize_t GrpListLen(PyObject *Self) +{ + return GetCpp<GrpListStruct>(Self).Iter.Cache()->HeaderP->GroupCount; +} + +static PyObject *GrpListItem(PyObject *iSelf,Py_ssize_t Index) +{ + GrpListStruct &Self = GetCpp<GrpListStruct>(iSelf); + + if (!Self.move(Index)) + return 0; + return CppPyObject_NEW<pkgCache::GrpIterator>(GetOwner<GrpListStruct>(iSelf),&PyGroup_Type, + Self.Iter); +} + +static PySequenceMethods GrpListSeq = +{ + GrpListLen, + 0, // concat + 0, // repeat + GrpListItem, + 0, // slice + 0, // assign item + 0 // assign slice +}; + +static const char *grouplist_doc = + "A GroupList is an internally used structure to represent\n" + "the 'groups' attribute of apt_pkg.Cache objects in a more\n" + "efficient manner by creating Group objects only when they\n" + "are accessed."; + +PyTypeObject PyGroupList_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.GroupList", // tp_name + sizeof(CppPyObject<GrpListStruct>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<GrpListStruct>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &GrpListSeq, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + grouplist_doc, // tp_doc + CppTraverse<GrpListStruct>, // tp_traverse + CppClear<GrpListStruct>, // tp_clear +}; + + #define Owner (GetOwner<pkgCache::PkgIterator>(Self)) #define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \ { \ diff --git a/tests/test_group.py b/tests/test_group.py index c69e4dbb..3c3a5b7a 100644 --- a/tests/test_group.py +++ b/tests/test_group.py @@ -23,5 +23,10 @@ class TestGroup(unittest.TestCase): list(group) == list(group) + def test_cache_groups(self): + """group: Iterate over all groups""" + assert len(list(self.cache.groups)) == self.cache.group_count + + if __name__ == "__main__": unittest.main() |
