From f7adc2d7205e2fdbff7d808e8e4c262b65e3e05d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 5 Apr 2011 11:27:04 +0200 Subject: Add an 'is_multi_arch' attribute to apt_pkg.Cache --- python/cache.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'python') diff --git a/python/cache.cc b/python/cache.cc index 190d4f27..b5ebcce4 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -222,11 +222,18 @@ static PyObject *PkgCacheGetFileList(PyObject *Self, void*) { return List; } +static PyObject *PkgCacheGetIsMultiArch(PyObject *Self, void*) { + pkgCache *Cache = GetCpp(Self); + PyBool_FromLong(Cache->MultiArchCache()); +} + static PyGetSetDef PkgCacheGetSet[] = { {"depends_count",PkgCacheGetDependsCount,0, "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."}, + {"is_multi_arch", PkgCacheGetIsMultiArch, 0, + "Whether the cache supports multi-arch."}, {"package_count",PkgCacheGetPackageCount,0, "The number of apt_pkg.Package objects stored in the cache."}, {"package_file_count",PkgCacheGetPackageFileCount,0, -- cgit v1.2.3 From 4548cac388f26cec60f1cef028421db910385565 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 5 Apr 2011 14:37:16 +0200 Subject: Add apt_pkg.Group class, wrapping pkgCache::GrpIterator --- debian/changelog | 3 +- doc/source/c++/api.rst | 30 +++++++ doc/source/library/apt_pkg.rst | 41 +++++++++ python/apt_pkgmodule.cc | 4 + python/apt_pkgmodule.h | 3 + python/cachegroup.cc | 188 +++++++++++++++++++++++++++++++++++++++++ python/python-apt-helpers.cc | 1 + python/python-apt.h | 8 ++ setup.py | 3 +- tests/test_group.py | 27 ++++++ 10 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 python/cachegroup.cc create mode 100644 tests/test_group.py (limited to 'python') diff --git a/debian/changelog b/debian/changelog index 48ce8f71..99043a95 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,8 @@ python-apt (0.8.0~exp1) UNRELEASED; urgency=low * Disable the old-style API, and break all packages using it - * Add an 'is_multi_arch' attribute to apt_pkg.Cache + * Add an 'is_multi_arch' attribute to apt_pkg.Cache + * Add apt_pkg.Group class, wrapping pkgCache::GrpIterator -- Julian Andres Klode Tue, 05 Apr 2011 10:33:54 +0200 diff --git a/doc/source/c++/api.rst b/doc/source/c++/api.rst index 97ab24d1..4922d272 100644 --- a/doc/source/c++/api.rst +++ b/doc/source/c++/api.rst @@ -389,6 +389,36 @@ Description (pkgCache::DescIterator) Return the :ctype:`pkgCache::DescIterator` reference contained in the Python object *object*. + +Group (pkgCache::GrpIterator) +---------------------------------- +.. cvar:: PyTypeObject PyGroup_Type + + The type object for :class:`apt_pkg.Group` objects. + +.. cfunction:: int PyGroup_Check(PyObject *object) + + Check that the object *object* is an :class:`apt_pkg.Group` object, or + a subclass thereof. + +.. cfunction:: int PyGroup_CheckExact(PyObject *object) + + Check that the object *object* is an :class:`apt_pkg.Group` object + and no subclass thereof. + +.. cfunction:: PyObject* PyGroup_FromCpp(pkgCache::GrpIterator &cpp, bool delete, PyObject *owner) + + Create a new :class:`apt_pkg.Group` object from the :ctype:`pkgCache::GrpIterator` + reference given by the parameter *cpp*. If the parameter *delete* is + true, *cpp* will be deleted when the reference + count of the returned object reaches 0. The parameter *owner* should be + a PyObject of the type :cdata:`PyCache_Type`. + +.. cfunction:: pkgCache::GrpIterator& PyGroup_ToCpp(PyObject *object) + + Return the :ctype:`pkgCache::GrpIterator` reference contained in the + Python object *object*. + Hashes (Hashes) ---------------------------------- .. cvar:: PyTypeObject PyHashes_Type diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst index 16593fe8..1b75a154 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -436,6 +436,47 @@ Resolving Dependencies with :class:`ProblemResolver` Try to resolve the problems without installing or removing packages. +:class:`Group` of packages with the same name +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. class:: Group(cache: Cache, name: str) + + .. versionadded:: 0.8.0 + + A collection of packages in which all packages have the same name. Groups + are used in multi-arch environments, where two or more packages have the + same name, but different architectures. + + Group objects provide the following parts for sequential access: + + .. describe:: group[index] + + Get the package at the given **index** in the group. + + .. note:: + Groups are internally implemented using a linked list. The object + keeps a pointer to the current object and the first object, so + access to the first element, or accesses in order have a + complexity of O(1). Random-access complexity is ranges from + O(1) to O(n). + + Group objects also provide special methods to find single packages: + + .. method:: find_package(architecture: str) -> Package + + Find a package with the groups name and the architecture given + in the argument *architecture*. If no such package exists, return + ``None``. + + .. method:: find_preferred_package(prefer_nonvirtual: bool = True) -> Package + + Find the preferred package. This is the package of the native + architecture (specified in ``APT::Architecture``) if available, + or the package from the first foreign architecture. If no package + could be found, return ``None`` + + If **prefer_nonvirtual** is ``True``, the preferred package + will be a non-virtual package, if one exists. + :class:`Package` information ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index d1ac33e0..e14677b1 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -732,6 +732,9 @@ static struct _PyAptPkgAPIStruct API = { &PyVersion_Type, // version_type &PyVersion_FromCpp, // version_tocpp &PyVersion_ToCpp, // version_tocpp + &PyGroup_Type, // group_type + &PyGroup_FromCpp, // group_fromcpp + &PyGroup_ToCpp // group_tocpp }; @@ -811,6 +814,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"DependencyList",&PyDependencyList_Type); // NO __new__(), internal ADDTYPE(Module,"Package",&PyPackage_Type); // NO __new__() ADDTYPE(Module,"Version",&PyVersion_Type); // NO __new__() + ADDTYPE(Module,"Group", &PyGroup_Type); /* ============================ cdrom.cc ============================ */ ADDTYPE(Module,"Cdrom",&PyCdrom_Type); /* ========================= configuration.cc ========================= */ diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index da647c3f..0081a1a9 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -70,6 +70,7 @@ extern PyTypeObject PyCache_Type; extern PyTypeObject PyCacheFile_Type; extern PyTypeObject PyPackageList_Type; extern PyTypeObject PyDescription_Type; +extern PyTypeObject PyGroup_Type; extern PyTypeObject PyPackage_Type; extern PyTypeObject PyPackageFile_Type; extern PyTypeObject PyDependency_Type; @@ -149,6 +150,7 @@ extern PyTypeObject PyFileLock_Type; # define PyDependency_ToCpp GetCpp # define PyDependencyList_ToCpp GetCpp // TODO # define PyDescription_ToCpp GetCpp +# define PyGroup_ToCpp GetCpp # define PyHashes_ToCpp GetCpp # define PyHashString_ToCpp GetCpp # define PyIndexRecords_ToCpp GetCpp @@ -186,6 +188,7 @@ PyObject* PyHashString_FromCpp(HashString* const &obj, bool Delete, PyObject *Ow PyObject* PyIndexRecords_FromCpp(indexRecords* const &obj, bool Delete, PyObject *Owner); PyObject* PyMetaIndex_FromCpp(metaIndex* const &obj, bool Delete, PyObject *Owner); PyObject* PyPackage_FromCpp(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner); +PyObject* PyGroup_FromCpp(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner); PyObject* PyIndexFile_FromCpp(pkgIndexFile* const &obj, bool Delete, PyObject *Owner); PyObject* PyPackageFile_FromCpp(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner); //PyObject* PyPackageList_FromCpp(PkgListStruct const &obj, bool Delete, PyObject *Owner); diff --git a/python/cachegroup.cc b/python/cachegroup.cc new file mode 100644 index 00000000..4fc6c378 --- /dev/null +++ b/python/cachegroup.cc @@ -0,0 +1,188 @@ +/* + * cachegroup.cc - Wrapper around pkgCache::GrpIterator + * + * Copyright 2011 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include +#include "apt_pkgmodule.h" +#include "generic.h" +#include + +struct PyGroup : CppPyObject { + pkgCache::PkgIterator current; + int nextIndex; +}; + +static PyObject *group_new(PyTypeObject *type,PyObject *args, + PyObject *kwds) +{ + PyObject *pyCache; + char *name; + char *kwlist[] = {"cache", "name", NULL}; + if (PyArg_ParseTupleAndKeywords(args, kwds, "O!s", kwlist, + &PyCache_Type, &pyCache, + &name) == 0) + return 0; + + pkgCache *cache = GetCpp(pyCache); + + pkgCache::GrpIterator grp = cache->FindGrp(name); + + if (!grp.end()) { + return PyGroup_FromCpp(grp, true, pyCache); + } else { + PyErr_SetString(PyExc_KeyError, name); + return NULL; + } +} + +static const char group_find_package_doc[] = + "find_package(architecture: str) -> Package\n\n" + "Return a package for the given architecture, or None if none exists"; +static PyObject *group_find_package(PyObject *self,PyObject *args) +{ + pkgCache::GrpIterator grp = GetCpp(self); + PyObject *owner = GetOwner(self); + + char *architecture; + if (PyArg_ParseTuple(args, "s", &architecture) == 0) + return 0; + + pkgCache::PkgIterator pkg = grp.FindPkg(architecture); + + if (pkg.end()) { + Py_RETURN_NONE; + } else { + return PyPackage_FromCpp(pkg, true, owner ? owner : self); + } +} + +static const char group_find_preferred_package_doc[] = + "find_preferred_package(prefer_non_virtual: bool = True) -> Package\n\n" + "Return a package for the best architecture, either the native one\n" + "or the first found one. If none exists, return None. If non_virtual\n" + "is True, prefer non-virtual packages over virtual ones."; +static PyObject *group_find_preferred_package(PyObject *self,PyObject *args, + PyObject *kwds) +{ + pkgCache::GrpIterator grp = GetCpp(self); + PyObject *owner = GetOwner(self); + char nonvirtual = 1; + char *kwlist[] = {"prefer_non_virtual", NULL}; + if (PyArg_ParseTupleAndKeywords(args, kwds, "|b", kwlist, &nonvirtual) == 0) + return 0; + pkgCache::PkgIterator pkg = grp.FindPreferredPkg(nonvirtual); + + if (pkg.end()) { + Py_RETURN_NONE; + } else { + return PyPackage_FromCpp(pkg, true, owner); + } +} + +static PyMethodDef group_methods[] = { + {"find_package",group_find_package,METH_VARARGS,group_find_package_doc}, + {"find_preferred_package",(PyCFunction) group_find_preferred_package, + METH_VARARGS|METH_KEYWORDS,group_find_preferred_package_doc}, + {} +}; + +static PyObject *group_seq_item(PyObject *pySelf,Py_ssize_t index) +{ + PyGroup *self = static_cast(pySelf); + pkgCache::GrpIterator grp = GetCpp(self); + PyObject *owner = GetOwner(self); + + if (self->nextIndex > index || self->nextIndex == 0) { + self->nextIndex = 1; + new (&self->current) pkgCache::PkgIterator(grp.PackageList()); + } + + if (self->nextIndex != index + 1) { + while (self->nextIndex <= index && !self->current.end()) { + self->current = grp.NextPkg(self->current); + self->nextIndex++; + } + } + + if (self->current.end()) + return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index); + + return PyPackage_FromCpp(self->current, true, owner); +} + + +static PySequenceMethods group_as_sequence = +{ + 0, + 0, // concat + 0, // repeat + group_seq_item, + 0, // slice + 0, // assign item + 0 // assign slice +}; + + +static const char group_doc[] = "Group(cache, name)\n\n" + "Group of packages with the same name.\n\n" + "Provides access to all packages sharing a name. Can be used this\n" + "like a list, or by using the special find_*() methods. If you use\n" + "it as a sequence, make sure to access it linearly, as this uses a\n" + "linked list internally."; +PyTypeObject PyGroup_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Group", // tp_name + sizeof(PyGroup), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &group_as_sequence, // 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, // tp_flags + group_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + group_methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + group_new, // tp_new +}; diff --git a/python/python-apt-helpers.cc b/python/python-apt-helpers.cc index 7a0f20c4..f50f62c4 100644 --- a/python/python-apt-helpers.cc +++ b/python/python-apt-helpers.cc @@ -52,6 +52,7 @@ NEW_FROM(PyHashString_FromCpp,&PyHashString_Type,HashString*) NEW_FROM(PyIndexRecords_FromCpp,&PyIndexRecords_Type,indexRecords*) NEW_FROM(PyMetaIndex_FromCpp,&PyMetaIndex_Type,metaIndex*) NEW_FROM(PyPackage_FromCpp,&PyPackage_Type,pkgCache::PkgIterator) +NEW_FROM(PyGroup_FromCpp,&PyGroup_Type,pkgCache::GrpIterator) NEW_FROM(PyIndexFile_FromCpp,&PyIndexFile_Type,pkgIndexFile*) NEW_FROM(PyPackageFile_FromCpp,&PyPackageFile_Type,pkgCache::PkgFileIterator) //NEW_FROM(PyPackageList_FromCpp,&PyPackageList_Type,PkgListStruct) diff --git a/python/python-apt.h b/python/python-apt.h index b9fc9212..ca8b557b 100644 --- a/python/python-apt.h +++ b/python/python-apt.h @@ -167,6 +167,9 @@ struct _PyAptPkgAPIStruct { PyObject* (*version_fromcpp)(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner); pkgCache::VerIterator& (*version_tocpp)(PyObject *self); + PyTypeObject *group_type; + PyObject* (*group_fromcpp)(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner); + pkgCache::GrpIterator& (*group_tocpp)(PyObject *self); }; // Checking macros. @@ -184,6 +187,7 @@ struct _PyAptPkgAPIStruct { # define PyDependency_Check(op) PyObject_TypeCheck(op, &PyDependency_Type) # define PyDependencyList_Check(op) PyObject_TypeCheck(op, &PyDependencyList_Type) # define PyDescription_Check(op) PyObject_TypeCheck(op, &PyDescription_Type) +# define PyGroup_Check(op) PyObject_TypeCheck(op, &PyGroup_Type) # define PyHashes_Check(op) PyObject_TypeCheck(op, &PyHashes_Type) # define PyHashString_Check(op) PyObject_TypeCheck(op, &PyHashString_Type) # define PyIndexRecords_Check(op) PyObject_TypeCheck(op, &PyIndexRecords_Type) @@ -217,6 +221,7 @@ struct _PyAptPkgAPIStruct { # define PyDependencyList_CheckExact(op) (op->op_type == &PyDependencyList_Type) # define PyDescription_CheckExact(op) (op->op_type == &PyDescription_Type) # define PyHashes_CheckExact(op) (op->op_type == &PyHashes_Type) +# define PyGroup_CheckExact(op) (op->op_type == &PyGroup_Type) # define PyHashString_CheckExact(op) (op->op_type == &PyHashString_Type) # define PyIndexRecords_CheckExact(op) (op->op_type == &PyIndexRecords_Type) # define PyMetaIndex_CheckExact(op) (op->op_type == &PyMetaIndex_Type) @@ -260,6 +265,7 @@ static int import_apt_pkg(void) { # define PyDependency_Type *(_PyAptPkg_API->dependency_type) # define PyDependencyList_Type *(_PyAptPkg_API->dependencylist_type) # define PyDescription_Type *(_PyAptPkg_API->description_type) +# define PyGroup_Type *(_PyAptPkg_API->group_type) # define PyHashes_Type *(_PyAptPkg_API->hashes_type) # define PyHashString_Type *(_PyAptPkg_API->hashstring_type) # define PyIndexRecords_Type *(_PyAptPkg_API->indexrecords_type) @@ -292,6 +298,7 @@ static int import_apt_pkg(void) { # define PyDependency_ToCpp _PyAptPkg_API->dependency_tocpp # define PyDependencyList_ToCpp _PyAptPkg_API->dependencylist_tocpp // NULL # define PyDescription_ToCpp _PyAptPkg_API->description_tocpp +# define PyGroup_ToCpp _PyAptPkg_API->group_tocpp # define PyHashes_ToCpp _PyAptPkg_API->hashes_tocpp # define PyHashString_ToCpp _PyAptPkg_API->hashstring_tocpp # define PyIndexRecords_ToCpp _PyAptPkg_API->indexrecords_tocpp @@ -324,6 +331,7 @@ static int import_apt_pkg(void) { # define PyDependency_FromCpp _PyAptPkg_API->dependency_fromcpp # define PyDependencyList_FromCpp _PyAptPkg_API->dependencylist_fromcpp // NULL # define PyDescription_FromCpp _PyAptPkg_API->description_fromcpp +# define PyGroup_FromCpp _PyAptPkg_API->group_fromcpp # define PyHashes_FromCpp _PyAptPkg_API->hashes_fromcpp # define PyHashString_FromCpp _PyAptPkg_API->hashstring_fromcpp # define PyIndexRecords_FromCpp _PyAptPkg_API->indexrecords_fromcpp diff --git a/setup.py b/setup.py index 9c6eda60..7f832673 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,8 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', - 'lock.cc', 'acquire-item.cc', 'python-apt-helpers.cc'] + 'lock.cc', 'acquire-item.cc', 'python-apt-helpers.cc', + 'cachegroup.cc'] files = sorted(['python/' + fname for fname in files], key=lambda s: s[:-3]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) diff --git a/tests/test_group.py b/tests/test_group.py new file mode 100644 index 00000000..b705d90e --- /dev/null +++ b/tests/test_group.py @@ -0,0 +1,27 @@ +import unittest + +import apt_pkg + + +class TestGroup(unittest.TestCase): + + def setUp(self): + apt_pkg.init() + self.cache = apt_pkg.Cache() + + def test_pkgingroup(self): + """Check that each package belongs to the corresponding group""" + for pkg in self.cache.packages: + group = apt_pkg.Group(self.cache, pkg.name) + assert any(pkg.id == p.id for p in group) + + def test_iteration(self): + """Check that iteration works correctly.""" + for pkg in self.cache.packages: + group = apt_pkg.Group(self.cache, pkg.name) + + list(group) == list(group) + + +if __name__ == "__main__": + unittest.main() -- cgit v1.2.3 From 5cc6fcb55f1fa50094a56644178c5e728deb83a4 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 5 Apr 2011 14:46:16 +0200 Subject: Change apt_pkg.Cache() so that passing None for 'progress' results in no progress output --- debian/changelog | 2 ++ doc/source/library/apt_pkg.rst | 3 ++- python/cache.cc | 9 +++++++-- tests/test_apt_cache.py | 2 +- tests/test_cache_invocation.py | 4 ++-- tests/test_group.py | 2 +- 6 files changed, 15 insertions(+), 7 deletions(-) (limited to 'python') diff --git a/debian/changelog b/debian/changelog index 99043a95..55c97813 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,8 @@ python-apt (0.8.0~exp1) UNRELEASED; urgency=low * Disable the old-style API, and break all packages using it * Add an 'is_multi_arch' attribute to apt_pkg.Cache * Add apt_pkg.Group class, wrapping pkgCache::GrpIterator + * Change apt_pkg.Cache() so that passing None for 'progress' results in + no progress output -- Julian Andres Klode 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 1b75a154..709648ac 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -40,7 +40,8 @@ Working with the cache The constructor takes an optional argument which must be a subclass of :class:`apt.progress.base.OpProgress`. This object will then be used to display information during the cache opening process (or possible creation - of the cache). + of the cache). It may also be ``None``, in which case no progress will + be emitted. If not given, progress will be printed to standard output. .. describe:: cache[pkgname] diff --git a/python/cache.cc b/python/cache.cc index b5ebcce4..6f1585e5 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -299,7 +299,11 @@ static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) pkgCacheFile *Cache = new pkgCacheFile(); - if(pyCallbackInst != 0) { + if (pyCallbackInst == Py_None) { + OpProgress Prog; + if (Cache->Open(Prog,false) == false) + return HandleErrors(); + } else if(pyCallbackInst != 0) { // sanity check for the progress object, see #497049 if (PyObject_HasAttrString(pyCallbackInst, "done") != true) { PyErr_SetString(PyExc_ValueError, @@ -349,7 +353,8 @@ static char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n" "apt.progress.base.OpProgress() object (or similar) which reports\n" "progress information while the cache is being opened. If this\n" "parameter is not supplied, the progress will be reported in simple,\n" - "human-readable text to standard output.\n\n" + "human-readable text to standard output. If it is None, no output\n" + "will be made.\n\n" "The cache can be used like a mapping from package names to Package\n" "objects (although only getting items is supported)."; static PySequenceMethods CacheSeq = {0,0,0,0,0,0,0,CacheContains,0,0}; diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py index cccfc9c8..b4cc650d 100644 --- a/tests/test_apt_cache.py +++ b/tests/test_apt_cache.py @@ -70,7 +70,7 @@ class TestAptCache(unittest.TestCase): def test_low_level_pkg_provides(self): # low level cache provides list of the pkg - cache = apt_pkg.Cache() + cache = apt_pkg.Cache(progress=None) l = cache["mail-transport-agent"].provides_list # arbitrary number, just needs to be higher enough self.assertTrue(len(l), 5) diff --git a/tests/test_cache_invocation.py b/tests/test_cache_invocation.py index 6f4014de..a89ef557 100644 --- a/tests/test_cache_invocation.py +++ b/tests/test_cache_invocation.py @@ -14,7 +14,7 @@ class TestCache(unittest.TestCase): def test_wrong_invocation(self): """cache_invocation: Test wrong invocation.""" - apt_cache = apt_pkg.Cache(apt.progress.base.OpProgress()) + apt_cache = apt_pkg.Cache(progress=None) self.assertRaises(ValueError, apt_pkg.Cache, apt_cache) self.assertRaises(ValueError, apt_pkg.Cache, @@ -23,7 +23,7 @@ class TestCache(unittest.TestCase): def test_proper_invocation(self): """cache_invocation: Test correct invocation.""" - apt_cache = apt_pkg.Cache(apt.progress.base.OpProgress()) + apt_cache = apt_pkg.Cache(progress=None) apt_depcache = apt_pkg.DepCache(apt_cache) if __name__ == "__main__": diff --git a/tests/test_group.py b/tests/test_group.py index b705d90e..c69e4dbb 100644 --- a/tests/test_group.py +++ b/tests/test_group.py @@ -7,7 +7,7 @@ class TestGroup(unittest.TestCase): def setUp(self): apt_pkg.init() - self.cache = apt_pkg.Cache() + self.cache = apt_pkg.Cache(progress=None) def test_pkgingroup(self): """Check that each package belongs to the corresponding group""" -- cgit v1.2.3 From 1c6ecaa6776498d27bcce81fa769a677a587215a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 5 Apr 2011 15:18:12 +0200 Subject: Support (name, arch) tuples in apt_pkg.Cache mappings, wrapping FindPkg() with two string parameters. --- debian/changelog | 2 ++ doc/source/library/apt_pkg.rst | 25 +++++++++++++++++++++-- python/cache.cc | 46 ++++++++++++++++++++++++++---------------- 3 files changed, 54 insertions(+), 19 deletions(-) (limited to 'python') diff --git a/debian/changelog b/debian/changelog index 55c97813..f241e749 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,8 @@ python-apt (0.8.0~exp1) UNRELEASED; urgency=low * Add apt_pkg.Group class, wrapping pkgCache::GrpIterator * Change apt_pkg.Cache() so that passing None for 'progress' results in no progress output + * Support (name, arch) tuples in apt_pkg.Cache mappings, wrapping + FindPkg() with two string parameters. -- Julian Andres Klode 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 709648ac..74bba8db 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -43,15 +43,36 @@ Working with the cache of the cache). It may also be ``None``, in which case no progress will be emitted. If not given, progress will be printed to standard output. + .. note:: + + The cache supports colon-seperated name:architecture pairs. For + normal architectures, they are equal to a (name, architecture) + tuple. For the the "any" architecture behavior is different, as + "name:any" is equivalent to ("name:any", "any"). This is done so + that "name:any" matches all packages with that name which have + Multi-Arch: allowed set. + .. describe:: cache[pkgname] Return the :class:`Package()` object for the package name given by - *pkgname*. + *pkgname*. If *pkgname* includes a colon, the part after the colon + is used as the architecture. + + .. describe:: cache[name, architecture] + + Return the :class:`Package()` object for the package with the given + name and architecture. .. describe:: pkgname in cache Check whether a package with the name given by *pkgname* exists in - the cache. + the cache for the native architecture. If *pkgname* includes a + colon, the part after the colon is used as the architecture. + + .. describe:: (name, architecture) in cache + + Check whether a package with the given name and architecture exists + in the cache. .. method:: update(progress, sources [, pulse_interval]) -> bool diff --git a/python/cache.cc b/python/cache.cc index 6f1585e5..cb877eee 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -249,24 +249,37 @@ static PyGetSetDef PkgCacheGetSet[] = { {} }; +// Helper to call FindPkg(name) or FindPkg(name, architecture) +static pkgCache::PkgIterator CacheFindPkg(PyObject *self, PyObject *arg) +{ + const char *name; + const char *architecture; + pkgCache *cache = GetCpp(self); + name = PyObject_AsString(arg); -// Map access, operator [] -static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) -{ - pkgCache *Cache = GetCpp(Self); + if (name != NULL) + return cache->FindPkg(name); - // Get the name of the package, unicode and normal strings. - const char *Name = PyObject_AsString(Arg); - if (Name == NULL) - return 0; + PyErr_Clear(); + if (PyArg_ParseTuple(arg, "ss", &name, &architecture) == 0) { + PyErr_Clear(); + PyErr_Format(PyExc_TypeError, "Expected a string or a pair of strings"); + return pkgCache::PkgIterator(); + } - // Search for the package - pkgCache::PkgIterator Pkg = Cache->FindPkg(Name); + return cache->FindPkg(name, architecture); +} + +// Map access, operator [] +static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) +{ + pkgCache::PkgIterator Pkg = CacheFindPkg(Self, Arg); if (Pkg.end() == true) { - PyErr_SetString(PyExc_KeyError,Name); + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError,Arg); return 0; } @@ -276,11 +289,9 @@ static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) // Check whether the cache contains a package with a given name. static int CacheContains(PyObject *Self,PyObject *Arg) { - // Get the name of the package, unicode and normal strings. - const char *Name = PyObject_AsString(Arg); - if (Name == NULL) - return 0; - return (GetCpp(Self)->FindPkg(Name).end() == false); + bool res = (CacheFindPkg(Self, Arg).end() == false); + PyErr_Clear(); + return res; } static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) @@ -356,7 +367,8 @@ static char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n" "human-readable text to standard output. If it is None, no output\n" "will be made.\n\n" "The cache can be used like a mapping from package names to Package\n" - "objects (although only getting items is supported)."; + "objects (although only getting items is supported). Instead of a name,\n" + "a tuple of a name and an architecture may be used."; static PySequenceMethods CacheSeq = {0,0,0,0,0,0,0,CacheContains,0,0}; static PyMappingMethods CacheMap = {CacheMapLen,CacheMapOp,0}; PyTypeObject PyCache_Type = -- cgit v1.2.3 From 6ae5009c6cfe56b66a22848f80eff6239245f1e7 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 5 Apr 2011 15:56:14 +0200 Subject: Introduce apt_pkg.Cache.groups and apt_pkg.Cache.group_count --- debian/changelog | 1 + doc/source/library/apt_pkg.rst | 26 +++++++ python/apt_pkgmodule.cc | 1 + python/apt_pkgmodule.h | 1 + python/cache.cc | 153 +++++++++++++++++++++++++++++++++-------- tests/test_group.py | 5 ++ 6 files changed, 160 insertions(+), 27 deletions(-) (limited to 'python') 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 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 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 { + 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 { + 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(Self); + return Py_BuildValue("i",Cache->HeaderP->GroupCount); +} + +static PyObject *PkgCacheGetGroups(PyObject *Self, void*) { + pkgCache *Cache = GetCpp(Self); + return CppPyObject_NEW(Self,&PyGroupList_Type,Cache->GrpBegin()); +} + static PyObject *PkgCacheGetPackages(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); return CppPyObject_NEW(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(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(GetOwner(iSelf),&PyPackage_Type, Self.Iter); } @@ -525,6 +562,68 @@ PyTypeObject PyPackageList_Type = CppClear, // tp_clear }; +/* The same for groups */ +static Py_ssize_t GrpListLen(PyObject *Self) +{ + return GetCpp(Self).Iter.Cache()->HeaderP->GroupCount; +} + +static PyObject *GrpListItem(PyObject *iSelf,Py_ssize_t Index) +{ + GrpListStruct &Self = GetCpp(iSelf); + + if (!Self.move(Index)) + return 0; + return CppPyObject_NEW(GetOwner(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), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc, // 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, // tp_traverse + CppClear, // tp_clear +}; + + #define Owner (GetOwner(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() -- cgit v1.2.3 From d5e763e1920eadf0bc0d460abbf686c65db2a3b4 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 11 Apr 2011 10:13:15 +0200 Subject: apt_pkg: Raise error when parse_commandline gets empty argv (LP: #707416) --- debian/changelog | 1 + python/configuration.cc | 4 ++++ tests/test_configuration.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 tests/test_configuration.py (limited to 'python') diff --git a/debian/changelog b/debian/changelog index 9d708753..e71cd63a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,7 @@ python-apt (0.8.0~exp2) UNRELEASED; urgency=low * aptsources: Various cleanup work * all: Fix all instances of ResourceWarning about unclosed files * tests/test_apt_cache.py: Use assertTrue() instead of assert_() + * apt_pkg: Raise error when parse_commandline gets empty argv (LP: #707416) -- Julian Andres Klode Wed, 06 Apr 2011 09:46:52 +0200 diff --git a/python/configuration.cc b/python/configuration.cc index 93e92efa..b6a44b44 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -438,6 +438,10 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) return 0; } + if (PySequence_Length(Pargv) < 1) { + PyErr_SetString(PyExc_ValueError,"argv is an empty sequence"); + return 0; + } // Convert the option list int Length = PySequence_Length(POList); CommandLine::Args *OList = new CommandLine::Args[Length+1]; diff --git a/tests/test_configuration.py b/tests/test_configuration.py new file mode 100644 index 00000000..80509cff --- /dev/null +++ b/tests/test_configuration.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +# +# Copyright (C) 2011 Julian Andres Klode +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of apt_pkg.Configuration""" +import unittest + +import apt_pkg + + +class TestConfiguration(unittest.TestCase): + """Test various configuration things""" + + def setUp(self): + """Prepare the tests, create reference values...""" + apt_pkg.init_config() + + def test_lp707416(self): + """configuration: Test empty arguments (LP: #707416)""" + self.assertRaises(ValueError, apt_pkg.parse_commandline, + apt_pkg.config,[], []) + self.assertRaises(SystemError, apt_pkg.parse_commandline, + apt_pkg.config,[], ["cmd", "--arg0"]) + + +if __name__ == "__main__": + unittest.main() -- cgit v1.2.3 From 2a0f97e8ad0ed8ac7456b8dc785071bf1c3a1847 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 11 Apr 2011 11:44:20 +0200 Subject: apt_pkg: Fix time_to_str, time_rfc1123 to accept more correct values (time_to_str accepts unsigned long, time_rfc1123 long long, y2k31-correct). --- debian/changelog | 2 ++ python/string.cc | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'python') diff --git a/debian/changelog b/debian/changelog index e71cd63a..2272462a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,6 +6,8 @@ python-apt (0.8.0~exp2) UNRELEASED; urgency=low * all: Fix all instances of ResourceWarning about unclosed files * tests/test_apt_cache.py: Use assertTrue() instead of assert_() * apt_pkg: Raise error when parse_commandline gets empty argv (LP: #707416) + * apt_pkg: Fix time_to_str, time_rfc1123 to accept more correct values + (time_to_str accepts unsigned long, time_rfc1123 long long, y2k31-correct). -- Julian Andres Klode Wed, 06 Apr 2011 09:46:52 +0200 diff --git a/python/string.cc b/python/string.cc index 6a1ce4e2..a5016103 100644 --- a/python/string.cc +++ b/python/string.cc @@ -28,11 +28,11 @@ PyObject *Python(PyObject *Self,PyObject *Args) \ return CppPyString(CFunc(Str)); \ } -#define MkInt(Python,CFunc) \ +#define MkInt(Python,CFunc, ctype, pytype) \ PyObject *Python(PyObject *Self,PyObject *Args) \ { \ - int Val = 0; \ - if (PyArg_ParseTuple(Args,"i",&Val) == 0) \ + ctype Val = 0; \ + if (PyArg_ParseTuple(Args,pytype,&Val) == 0) \ return 0; \ return CppPyString(CFunc(Val)); \ } @@ -56,8 +56,8 @@ PyObject *StrBase64Encode(PyObject *Self,PyObject *Args) { MkStr(StrURItoFileName,URItoFileName); //MkFloat(StrSizeToStr,SizeToStr); -MkInt(StrTimeToStr,TimeToStr); -MkInt(StrTimeRFC1123,TimeRFC1123); +MkInt(StrTimeToStr,TimeToStr, unsigned long, "k"); +MkInt(StrTimeRFC1123,TimeRFC1123, long long, "L"); /*}}}*/ // Other String functions /*{{{*/ -- cgit v1.2.3 From f441b008883170d6a8c4cfeb814b0c07a27e6afd Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 12 Apr 2011 11:38:25 +0200 Subject: apt_pkg: Fix unsigned/long-vs-int issues (LP: #610820) This fix is large, but simple in concept. Instead of relying on Py_BuildValue and type signatures, or type-specific conversion functions, create a new set of overloaded MkPyNumber() functions that automatically do the right thing for each numerical type. --- debian/changelog | 1 + python/acquire-item.cc | 10 ++++---- python/acquire.cc | 14 +++++----- python/apt_pkgmodule.cc | 68 ++++++++++++++++++++++++------------------------- python/arfile.cc | 12 ++++----- python/cache.cc | 44 ++++++++++++++++---------------- python/configuration.cc | 2 +- python/depcache.cc | 12 ++++----- python/generic.h | 16 ++++++++++++ python/indexfile.cc | 2 +- python/indexrecords.cc | 2 +- python/pkgmanager.cc | 2 +- python/pkgsrcrecords.cc | 10 +++++--- python/policy.cc | 2 +- python/progress.cc | 60 +++++++++++++++++++++---------------------- python/string.cc | 4 +-- python/tag.cc | 5 ++-- python/tarfile.cc | 14 +++++----- 18 files changed, 150 insertions(+), 130 deletions(-) (limited to 'python') diff --git a/debian/changelog b/debian/changelog index ae57e18b..1460acce 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,7 @@ python-apt (0.8.0~exp2) UNRELEASED; urgency=low * apt.progress: Use long for ETA, natural type for size (LP: #377375) * aptsources/sourceslist.py: s/aptsource.py/sourceslist.py/ (LP: #309603) * doc/examples: Add example on how to get architecture names (LP: #194374) + * apt_pkg: Fix unsigned/long-vs-int issues (LP: #610820) -- Julian Andres Klode Wed, 06 Apr 2011 09:46:52 +0200 diff --git a/python/acquire-item.cc b/python/acquire-item.cc index 895d4a21..5e7423ab 100644 --- a/python/acquire-item.cc +++ b/python/acquire-item.cc @@ -65,13 +65,13 @@ static PyObject *acquireitem_get_error_text(PyObject *self, void *closure) static PyObject *acquireitem_get_filesize(PyObject *self, void *closure) { pkgAcquire::Item *item = acquireitem_tocpp(self); - return item ? Py_BuildValue("K", item->FileSize) : 0; + return item ? MkPyNumber(item->FileSize) : 0; } static PyObject *acquireitem_get_id(PyObject *self, void *closure) { pkgAcquire::Item *item = acquireitem_tocpp(self); - return item ? Py_BuildValue("k", item->ID) : 0; + return item ? MkPyNumber(item->ID) : 0; } static PyObject *acquireitem_get_mode(PyObject *self, void *closure) @@ -95,13 +95,13 @@ static PyObject *acquireitem_get_local(PyObject *self, void *closure) static PyObject *acquireitem_get_partialsize(PyObject *self, void *closure) { pkgAcquire::Item *item = acquireitem_tocpp(self); - return item ? Py_BuildValue("K", item->PartialSize) : 0; + return item ? MkPyNumber(item->PartialSize) : 0; } static PyObject *acquireitem_get_status(PyObject *self, void *closure) { pkgAcquire::Item *item = acquireitem_tocpp(self); - return item ? Py_BuildValue("i", item->Status) : 0; + return item ? MkPyNumber(item->Status) : 0; } static int acquireitem_set_id(PyObject *self, PyObject *value, void *closure) @@ -110,7 +110,7 @@ static int acquireitem_set_id(PyObject *self, PyObject *value, void *closure) if (Itm == 0) return -1; if (PyLong_Check(value)) { - Itm->ID = PyLong_AsLong(value); + Itm->ID = PyLong_AsUnsignedLong(value); } else if (PyInt_Check(value)) { Itm->ID = PyInt_AsLong(value); diff --git a/python/acquire.cc b/python/acquire.cc index ab90bbdd..6169ff40 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -51,17 +51,17 @@ static PyObject *acquireworker_get_status(PyObject *self, void *closure) static PyObject *acquireworker_get_current_size(PyObject *self, void *closure) { - return Py_BuildValue("k",GetCpp(self)->CurrentSize); + return MkPyNumber(GetCpp(self)->CurrentSize); } static PyObject *acquireworker_get_total_size(PyObject *self, void *closure) { - return Py_BuildValue("k",GetCpp(self)->TotalSize); + return MkPyNumber(GetCpp(self)->TotalSize); } static PyObject *acquireworker_get_resumepoint(PyObject *self, void *closure) { - return Py_BuildValue("k",GetCpp(self)->ResumePoint); + return MkPyNumber(GetCpp(self)->ResumePoint); } static PyGetSetDef acquireworker_getset[] = { @@ -225,7 +225,7 @@ static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args) pkgAcquire::RunResult run = fetcher->Run(pulseInterval); - return HandleErrors(Py_BuildValue("i",run)); + return HandleErrors(MkPyNumber(run)); } @@ -259,15 +259,15 @@ static PyMethodDef PkgAcquireMethods[] = { #define fetcher (GetCpp(Self)) static PyObject *PkgAcquireGetTotalNeeded(PyObject *Self,void*) { - return Py_BuildValue("L", fetcher->TotalNeeded()); + return MkPyNumber(fetcher->TotalNeeded()); } static PyObject *PkgAcquireGetFetchNeeded(PyObject *Self,void*) { - return Py_BuildValue("L", fetcher->FetchNeeded()); + return MkPyNumber(fetcher->FetchNeeded()); } static PyObject *PkgAcquireGetPartialPresent(PyObject *Self,void*) { - return Py_BuildValue("L", fetcher->PartialPresent()); + return MkPyNumber(fetcher->PartialPresent()); } #undef fetcher diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 0fac664b..2394b0f8 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -83,7 +83,7 @@ static PyObject *VersionCompare(PyObject *Self,PyObject *Args) return 0; } - return Py_BuildValue("i",_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB)); + return MkPyNumber(_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB)); } static char *doc_CheckDep = @@ -459,7 +459,7 @@ static PyObject *GetLock(PyObject *Self,PyObject *Args) int fd = GetLock(file, errors); - return HandleErrors(Py_BuildValue("i", fd)); + return HandleErrors(MkPyNumber(fd)); } static char *doc_PkgSystemLock = @@ -854,82 +854,82 @@ extern "C" void initapt_pkg() // Acquire constants. // some constants PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CANCELLED", - Py_BuildValue("i", pkgAcquire::Cancelled)); + MkPyNumber(pkgAcquire::Cancelled)); PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CONTINUE", - Py_BuildValue("i", pkgAcquire::Continue)); + MkPyNumber(pkgAcquire::Continue)); PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_FAILED", - Py_BuildValue("i", pkgAcquire::Failed)); + MkPyNumber(pkgAcquire::Failed)); #ifdef COMPAT_0_7 PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultCancelled", - Py_BuildValue("i", pkgAcquire::Cancelled)); + MkPyNumber(pkgAcquire::Cancelled)); PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultContinue", - Py_BuildValue("i", pkgAcquire::Continue)); + MkPyNumber(pkgAcquire::Continue)); PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultFailed", - Py_BuildValue("i", pkgAcquire::Failed)); + MkPyNumber(pkgAcquire::Failed)); #endif // Dependency constants PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DEPENDS", - Py_BuildValue("i", pkgCache::Dep::Depends)); + MkPyNumber(pkgCache::Dep::Depends)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_PREDEPENDS", - Py_BuildValue("i", pkgCache::Dep::PreDepends)); + MkPyNumber(pkgCache::Dep::PreDepends)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_SUGGESTS", - Py_BuildValue("i", pkgCache::Dep::Suggests)); + MkPyNumber(pkgCache::Dep::Suggests)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_RECOMMENDS", - Py_BuildValue("i", pkgCache::Dep::Suggests)); + MkPyNumber(pkgCache::Dep::Suggests)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_CONFLICTS", - Py_BuildValue("i", pkgCache::Dep::Conflicts)); + MkPyNumber(pkgCache::Dep::Conflicts)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_REPLACES", - Py_BuildValue("i", pkgCache::Dep::Replaces)); + MkPyNumber(pkgCache::Dep::Replaces)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_OBSOLETES", - Py_BuildValue("i", pkgCache::Dep::Obsoletes)); + MkPyNumber(pkgCache::Dep::Obsoletes)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DPKG_BREAKS", - Py_BuildValue("i", pkgCache::Dep::DpkgBreaks)); + MkPyNumber(pkgCache::Dep::DpkgBreaks)); PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_ENHANCES", - Py_BuildValue("i", pkgCache::Dep::Enhances)); + MkPyNumber(pkgCache::Dep::Enhances)); // PackageManager constants PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_COMPLETED", - Py_BuildValue("i", pkgPackageManager::Completed)); + MkPyNumber(pkgPackageManager::Completed)); PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_FAILED", - Py_BuildValue("i", pkgPackageManager::Failed)); + MkPyNumber(pkgPackageManager::Failed)); PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_INCOMPLETE", - Py_BuildValue("i", pkgPackageManager::Incomplete)); + MkPyNumber(pkgPackageManager::Incomplete)); #ifdef COMPAT_0_7 PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultCompleted", - Py_BuildValue("i", pkgPackageManager::Completed)); + MkPyNumber(pkgPackageManager::Completed)); PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultFailed", - Py_BuildValue("i", pkgPackageManager::Failed)); + MkPyNumber(pkgPackageManager::Failed)); PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultIncomplete", - Py_BuildValue("i", pkgPackageManager::Incomplete)); + MkPyNumber(pkgPackageManager::Incomplete)); #endif // AcquireItem Constants. PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_IDLE", - Py_BuildValue("i", pkgAcquire::Item::StatIdle)); + MkPyNumber(pkgAcquire::Item::StatIdle)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_FETCHING", - Py_BuildValue("i", pkgAcquire::Item::StatFetching)); + MkPyNumber(pkgAcquire::Item::StatFetching)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_DONE", - Py_BuildValue("i", pkgAcquire::Item::StatDone)); + MkPyNumber(pkgAcquire::Item::StatDone)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_TRANSIENT_NETWORK_ERROR", - Py_BuildValue("i", pkgAcquire::Item::StatTransientNetworkError)); + MkPyNumber(pkgAcquire::Item::StatTransientNetworkError)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_ERROR", - Py_BuildValue("i", pkgAcquire::Item::StatError)); + MkPyNumber(pkgAcquire::Item::StatError)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_AUTH_ERROR", - Py_BuildValue("i", pkgAcquire::Item::StatAuthError)); + MkPyNumber(pkgAcquire::Item::StatAuthError)); #ifdef COMPAT_0_7 PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatIdle", - Py_BuildValue("i", pkgAcquire::Item::StatIdle)); + MkPyNumber(pkgAcquire::Item::StatIdle)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatFetching", - Py_BuildValue("i", pkgAcquire::Item::StatFetching)); + MkPyNumber(pkgAcquire::Item::StatFetching)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatDone", - Py_BuildValue("i", pkgAcquire::Item::StatDone)); + MkPyNumber(pkgAcquire::Item::StatDone)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatError", - Py_BuildValue("i", pkgAcquire::Item::StatError)); + MkPyNumber(pkgAcquire::Item::StatError)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatAuthError", - Py_BuildValue("i", pkgAcquire::Item::StatAuthError)); + MkPyNumber(pkgAcquire::Item::StatAuthError)); #endif #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 diff --git a/python/arfile.cc b/python/arfile.cc index 5377ca8d..c3aa74d1 100644 --- a/python/arfile.cc +++ b/python/arfile.cc @@ -39,32 +39,32 @@ static PyObject *armember_get_name(PyObject *self, void *closure) static PyObject *armember_get_mtime(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self)->MTime); + return MkPyNumber(GetCpp(self)->MTime); } static PyObject *armember_get_uid(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self)->UID); + return MkPyNumber(GetCpp(self)->UID); } static PyObject *armember_get_gid(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self)->GID); + return MkPyNumber(GetCpp(self)->GID); } static PyObject *armember_get_mode(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self)->Mode); + return MkPyNumber(GetCpp(self)->Mode); } static PyObject *armember_get_size(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self)->Size); + return MkPyNumber(GetCpp(self)->Size); } static PyObject *armember_get_start(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self)->Start); + return MkPyNumber(GetCpp(self)->Start); } static PyObject *armember_repr(PyObject *self) diff --git a/python/cache.cc b/python/cache.cc index a27bf6f5..160fd208 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -221,7 +221,7 @@ static PyMethodDef PkgCacheMethods[] = static PyObject *PkgCacheGetGroupCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); - return Py_BuildValue("i",Cache->HeaderP->GroupCount); + return MkPyNumber(Cache->HeaderP->GroupCount); } static PyObject *PkgCacheGetGroups(PyObject *Self, void*) { @@ -236,31 +236,31 @@ static PyObject *PkgCacheGetPackages(PyObject *Self, void*) { static PyObject *PkgCacheGetPackageCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); - return Py_BuildValue("i",Cache->HeaderP->PackageCount); + return MkPyNumber((int)Cache->HeaderP->PackageCount); } static PyObject *PkgCacheGetVersionCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); - return Py_BuildValue("i",Cache->HeaderP->VersionCount); + return MkPyNumber(Cache->HeaderP->VersionCount); } static PyObject *PkgCacheGetDependsCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); - return Py_BuildValue("i",Cache->HeaderP->DependsCount); + return MkPyNumber(Cache->HeaderP->DependsCount); } static PyObject *PkgCacheGetPackageFileCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); - return Py_BuildValue("i",Cache->HeaderP->PackageFileCount); + return MkPyNumber(Cache->HeaderP->PackageFileCount); } static PyObject *PkgCacheGetVerFileCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); - return Py_BuildValue("i",Cache->HeaderP->VerFileCount); + return MkPyNumber(Cache->HeaderP->VerFileCount); } static PyObject *PkgCacheGetProvidesCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp(Self); - return Py_BuildValue("i",Cache->HeaderP->ProvidesCount); + return MkPyNumber(Cache->HeaderP->ProvidesCount); } static PyObject *PkgCacheGetFileList(PyObject *Self, void*) { @@ -637,10 +637,10 @@ MkGet(PackageGetSection,Safe_FromString(Pkg.Section())) MkGet(PackageGetRevDependsList,CppPyObject_NEW(Owner, &PyDependencyList_Type, Pkg.RevDependsList())) MkGet(PackageGetProvidesList,CreateProvides(Owner,Pkg.ProvidesList())) -MkGet(PackageGetSelectedState,Py_BuildValue("i",Pkg->SelectedState)) -MkGet(PackageGetInstState,Py_BuildValue("i",Pkg->InstState)) -MkGet(PackageGetCurrentState,Py_BuildValue("i",Pkg->CurrentState)) -MkGet(PackageGetID,Py_BuildValue("i",Pkg->ID)) +MkGet(PackageGetSelectedState,MkPyNumber(Pkg->SelectedState)) +MkGet(PackageGetInstState,MkPyNumber(Pkg->InstState)) +MkGet(PackageGetCurrentState,MkPyNumber(Pkg->CurrentState)) +MkGet(PackageGetID,MkPyNumber(Pkg->ID)) # MkGet(PackageGetAuto,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Auto) != 0)) MkGet(PackageGetEssential,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Essential) != 0)) @@ -837,7 +837,7 @@ static PyObject *DescriptionGetFileList(PyObject *Self,void*) PyObject *DescFile; PyObject *Obj; DescFile = CppPyObject_NEW(Owner,&PyPackageFile_Type,I.File()); - Obj = Py_BuildValue("Nl",DescFile,I.Index()); + Obj = Py_BuildValue("NN",DescFile,MkPyNumber(I.Index())); PyList_Append(List,Obj); Py_DECREF(Obj); } @@ -992,7 +992,7 @@ static PyObject *VersionGetFileList(PyObject *Self, void*) { PyObject *PkgFile; PyObject *Obj; PkgFile = CppPyObject_NEW(Owner,&PyPackageFile_Type,I.File()); - Obj = Py_BuildValue("Nl",PkgFile,I.Index()); + Obj = Py_BuildValue("NN",PkgFile,MkPyNumber(I.Index())); PyList_Append(List,Obj); Py_DECREF(Obj); } @@ -1019,19 +1019,19 @@ static PyObject *VersionGetProvidesList(PyObject *Self, void*) { return CreateProvides(Owner,Version_GetVer(Self).ProvidesList()); } static PyObject *VersionGetSize(PyObject *Self, void*) { - return Py_BuildValue("i", Version_GetVer(Self)->Size); + return MkPyNumber(Version_GetVer(Self)->Size); } static PyObject *VersionGetInstalledSize(PyObject *Self, void*) { - return Py_BuildValue("i", Version_GetVer(Self)->InstalledSize); + return MkPyNumber(Version_GetVer(Self)->InstalledSize); } static PyObject *VersionGetHash(PyObject *Self, void*) { - return Py_BuildValue("i", Version_GetVer(Self)->Hash); + return MkPyNumber(Version_GetVer(Self)->Hash); } static PyObject *VersionGetID(PyObject *Self, void*) { - return Py_BuildValue("i", Version_GetVer(Self)->ID); + return MkPyNumber(Version_GetVer(Self)->ID); } static PyObject *VersionGetPriority(PyObject *Self, void*) { - return Py_BuildValue("i",Version_GetVer(Self)->Priority); + return MkPyNumber(Version_GetVer(Self)->Priority); } static PyObject *VersionGetPriorityStr(PyObject *Self, void*) { return Safe_FromString(Version_GetVer(Self).PriorityType()); @@ -1241,7 +1241,7 @@ static PyObject *PackageFile_GetIndexType(PyObject *Self,void*) static PyObject *PackageFile_GetSize(PyObject *Self,void*) { pkgCache::PkgFileIterator &File = GetCpp(Self); - return Py_BuildValue("i",File->Size); + return MkPyNumber(File->Size); } static PyObject *PackageFile_GetNotSource(PyObject *Self,void*) @@ -1258,7 +1258,7 @@ static PyObject *PackageFile_GetNotAutomatic(PyObject *Self,void*) static PyObject *PackageFile_GetID(PyObject *Self,void*) { pkgCache::PkgFileIterator &File = GetCpp(Self); - return Py_BuildValue("i",File->ID); + return MkPyNumber(File->ID); } #define S(s) (s == NULL ? "" : s) @@ -1467,13 +1467,13 @@ static PyObject *DependencyGetDepTypeUntranslated(PyObject *Self,void*) static PyObject *DependencyGetDepTypeEnum(PyObject *Self,void*) { pkgCache::DepIterator &Dep = GetCpp(Self); - return Py_BuildValue("i", Dep->Type); + return MkPyNumber(Dep->Type); } static PyObject *DependencyGetID(PyObject *Self,void*) { pkgCache::DepIterator &Dep = GetCpp(Self); - return Py_BuildValue("i",Dep->ID); + return MkPyNumber(Dep->ID); } static PyGetSetDef DependencyGetSet[] = { diff --git a/python/configuration.cc b/python/configuration.cc index b6a44b44..9000f71f 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -92,7 +92,7 @@ static PyObject *CnfFindI(PyObject *Self,PyObject *Args) int Default = 0; if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0) return 0; - return Py_BuildValue("i",GetSelf(Self).FindI(Name,Default)); + return MkPyNumber(GetSelf(Self).FindI(Name,Default)); } static const char *doc_FindB = diff --git a/python/depcache.cc b/python/depcache.cc index 12c13a73..e6113429 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -668,22 +668,22 @@ static PyMethodDef PkgDepCacheMethods[] = #define depcache (GetCpp(Self)) static PyObject *PkgDepCacheGetKeepCount(PyObject *Self,void*) { - return Py_BuildValue("l", depcache->KeepCount()); + return MkPyNumber(depcache->KeepCount()); } static PyObject *PkgDepCacheGetInstCount(PyObject *Self,void*) { - return Py_BuildValue("l", depcache->InstCount()); + return MkPyNumber(depcache->InstCount()); } static PyObject *PkgDepCacheGetDelCount(PyObject *Self,void*) { - return Py_BuildValue("l", depcache->DelCount()); + return MkPyNumber(depcache->DelCount()); } static PyObject *PkgDepCacheGetBrokenCount(PyObject *Self,void*) { - return Py_BuildValue("l", depcache->BrokenCount()); + return MkPyNumber(depcache->BrokenCount()); } static PyObject *PkgDepCacheGetUsrSize(PyObject *Self,void*) { - return Py_BuildValue("L", depcache->UsrSize()); + return MkPyNumber(depcache->UsrSize()); } static PyObject *PkgDepCacheGetDebSize(PyObject *Self,void*) { - return Py_BuildValue("L", depcache->DebSize()); + return MkPyNumber(depcache->DebSize()); } #undef depcache diff --git a/python/generic.h b/python/generic.h index ce9e5091..f9680ca5 100644 --- a/python/generic.h +++ b/python/generic.h @@ -57,6 +57,7 @@ typedef int Py_ssize_t; #define PyString_Type PyUnicode_Type #define PyInt_Check PyLong_Check #define PyInt_AsLong PyLong_AsLong +#define PyInt_FromLong PyLong_FromLong // Force 0.7 compatibility to be off in Python 3 builds #undef COMPAT_0_7 #else @@ -231,6 +232,21 @@ PyObject *HandleErrors(PyObject *Res = 0); const char **ListToCharChar(PyObject *List,bool NullTerm = false); PyObject *CharCharToList(const char **List,unsigned long Size = 0); +/* Happy number conversion, thanks to overloading */ +inline PyObject *MkPyNumber(unsigned long long o) { return PyLong_FromUnsignedLongLong(o); } +inline PyObject *MkPyNumber(unsigned long o) { return PyLong_FromUnsignedLong(o); } +inline PyObject *MkPyNumber(unsigned int o) { return PyLong_FromUnsignedLong(o); } +inline PyObject *MkPyNumber(unsigned short o) { return PyInt_FromLong(o); } +inline PyObject *MkPyNumber(unsigned char o) { return PyInt_FromLong(o); } + +inline PyObject *MkPyNumber(long long o) { return PyLong_FromLongLong(o); } +inline PyObject *MkPyNumber(long o) { return PyInt_FromLong(o); } +inline PyObject *MkPyNumber(int o) { return PyInt_FromLong(o); } +inline PyObject *MkPyNumber(short o) { return PyInt_FromLong(o); } +inline PyObject *MkPyNumber(char o) { return PyInt_FromLong(o); } + +inline PyObject *MkPyNumber(double o) { return PyFloat_FromDouble(o); } + # ifdef COMPAT_0_7 PyObject *_PyAptObject_getattro(PyObject *self, PyObject *attr); # else diff --git a/python/indexfile.cc b/python/indexfile.cc index 037be210..bf0df516 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -47,7 +47,7 @@ static PyObject *IndexFileGetHasPackages(PyObject *Self,void*) { return PyBool_FromLong((File->HasPackages())); } static PyObject *IndexFileGetSize(PyObject *Self,void*) { - return Py_BuildValue("i",(File->Size())); + return MkPyNumber((File->Size())); } static PyObject *IndexFileGetIsTrusted(PyObject *Self,void*) { return PyBool_FromLong((File->IsTrusted())); diff --git a/python/indexrecords.cc b/python/indexrecords.cc index d6a3263c..c7623cfd 100644 --- a/python/indexrecords.cc +++ b/python/indexrecords.cc @@ -63,7 +63,7 @@ static PyObject *indexrecords_lookup(PyObject *self,PyObject *args) // Copy the HashString(), to prevent crashes and to not require the // indexRecords object to exist. PyObject *py_hash = PyHashString_FromCpp(new HashString(result->Hash), true, NULL); - PyObject *value = Py_BuildValue("(Oi)",py_hash,result->Size); + PyObject *value = Py_BuildValue("(ON)",py_hash,MkPyNumber(result->Size)); Py_DECREF(py_hash); return value; } diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index 95e8c27e..a65c88f8 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -79,7 +79,7 @@ static PyObject *PkgManagerDoInstall(PyObject *Self,PyObject *Args) pkgPackageManager::OrderResult res = pm->DoInstall(status_fd); - return HandleErrors(Py_BuildValue("i",res)); + return HandleErrors(MkPyNumber(res)); } static PyObject *PkgManagerFixMissing(PyObject *Self,PyObject *Args) diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc index aad3ef7e..4c889129 100644 --- a/python/pkgsrcrecords.cc +++ b/python/pkgsrcrecords.cc @@ -147,9 +147,9 @@ static PyObject *PkgSrcRecordsGetFiles(PyObject *Self,void*) { PyObject *v; for(unsigned int i=0;i(self); if (PyObject_TypeCheck(arg, &PyPackage_Type)) { pkgCache::PkgIterator pkg = GetCpp(arg); - return Py_BuildValue("i", policy->GetPriority(pkg)); + return MkPyNumber(policy->GetPriority(pkg)); } else { PyErr_SetString(PyExc_TypeError,"Argument must be of Package()."); return 0; diff --git a/python/progress.cc b/python/progress.cc index 5700a1b6..bd3c2ad6 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -92,12 +92,12 @@ void PyOpProgress::Update() setattr(callbackInst, "op", "s", Op.c_str()); setattr(callbackInst, "subop", "s", SubOp.c_str()); setattr(callbackInst, "major_change", "b", MajorChange); - setattr(callbackInst, "percent", "f", Percent); + setattr(callbackInst, "percent", "N", MkPyNumber(Percent)); #ifdef COMPAT_0_7 setattr(callbackInst, "Op", "s", Op.c_str()); setattr(callbackInst, "subOp", "s", SubOp.c_str()); setattr(callbackInst, "majorChange", "b", MajorChange); - PyObject *arglist = Py_BuildValue("(f)", Percent); + PyObject *arglist = Py_BuildValue("(N)", MkPyNumber(Percent)); RunSimpleCallback("update", arglist); #else RunSimpleCallback("update"); @@ -156,19 +156,19 @@ void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status) // Added object file size and object partial size to // parameters that are passed to updateStatus. // -- Stephan - PyObject *arglist = Py_BuildValue("(sssikk)", Itm.URI.c_str(), + PyObject *arglist = Py_BuildValue("(sssNNN)", Itm.URI.c_str(), Itm.Description.c_str(), Itm.ShortDesc.c_str(), - status, - Itm.Owner->FileSize, - Itm.Owner->PartialSize); + MkPyNumber(status), + MkPyNumber(Itm.Owner->FileSize), + MkPyNumber(Itm.Owner->PartialSize)); RunSimpleCallback("update_status_full", arglist); // legacy version of the interface - arglist = Py_BuildValue("(sssi)", Itm.URI.c_str(), Itm.Description.c_str(), - Itm.ShortDesc.c_str(), status); + arglist = Py_BuildValue("(sssN)", Itm.URI.c_str(), Itm.Description.c_str(), + Itm.ShortDesc.c_str(), MkPyNumber(status)); if(PyObject_HasAttrString(callbackInst, "updateStatus")) RunSimpleCallback("updateStatus", arglist); @@ -240,11 +240,11 @@ void PyFetchProgress::Start() pkgAcquireStatus::Start(); #ifdef COMPAT_0_7 - setattr(callbackInst, "currentCPS", "d", 0); - setattr(callbackInst, "currentBytes", "d", 0); - setattr(callbackInst, "currentItems", "k", 0); - setattr(callbackInst, "totalItems", "k", 0); - setattr(callbackInst, "totalBytes", "d", 0); + setattr(callbackInst, "currentCPS", "N", MkPyNumber(0)); + setattr(callbackInst, "currentBytes", "N", MkPyNumber(0)); + setattr(callbackInst, "currentItems", "N", MkPyNumber(0)); + setattr(callbackInst, "totalItems", "N", MkPyNumber(0)); + setattr(callbackInst, "totalBytes", "N", MkPyNumber(0)); #endif RunSimpleCallback("start"); @@ -280,14 +280,14 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) return false; } - setattr(callbackInst, "last_bytes", "d", LastBytes); - setattr(callbackInst, "current_cps", "d", CurrentCPS); - setattr(callbackInst, "current_bytes", "d", CurrentBytes); - setattr(callbackInst, "total_bytes", "d", TotalBytes); - setattr(callbackInst, "fetched_bytes", "d", FetchedBytes); - setattr(callbackInst, "elapsed_time", "k", ElapsedTime); - setattr(callbackInst, "current_items", "k", CurrentItems); - setattr(callbackInst, "total_items", "k", TotalItems); + setattr(callbackInst, "last_bytes", "N", MkPyNumber(LastBytes)); + setattr(callbackInst, "current_cps", "N", MkPyNumber(CurrentCPS)); + setattr(callbackInst, "current_bytes", "N", MkPyNumber(CurrentBytes)); + setattr(callbackInst, "total_bytes", "N", MkPyNumber(TotalBytes)); + setattr(callbackInst, "fetched_bytes", "N", MkPyNumber(FetchedBytes)); + setattr(callbackInst, "elapsed_time", "N", MkPyNumber(ElapsedTime)); + setattr(callbackInst, "current_items", "N", MkPyNumber(CurrentItems)); + setattr(callbackInst, "total_items", "N", MkPyNumber(TotalItems)); // New style if (!PyObject_HasAttrString(callbackInst, "updateStatus")) { @@ -313,12 +313,12 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) return true; } #ifdef COMPAT_0_7 - setattr(callbackInst, "currentCPS", "d", CurrentCPS); - setattr(callbackInst, "currentBytes", "d", CurrentBytes); - setattr(callbackInst, "totalBytes", "d", TotalBytes); - setattr(callbackInst, "fetchedBytes", "d", FetchedBytes); - setattr(callbackInst, "currentItems", "k", CurrentItems); - setattr(callbackInst, "totalItems", "k", TotalItems); + setattr(callbackInst, "currentCPS", "N", MkPyNumber(CurrentCPS)); + setattr(callbackInst, "currentBytes", "N", MkPyNumber(CurrentBytes)); + setattr(callbackInst, "totalBytes", "N", MkPyNumber(TotalBytes)); + setattr(callbackInst, "fetchedBytes", "N", MkPyNumber(FetchedBytes)); + setattr(callbackInst, "currentItems", "N", MkPyNumber(CurrentItems)); + setattr(callbackInst, "totalItems", "N", MkPyNumber(TotalItems)); // Go through the list of items and add active items to the // activeItems vector. map activeItemMap; @@ -351,11 +351,11 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) pkgAcquire::Worker *worker = iter->first; pkgAcquire::ItemDesc *itm = iter->second; - PyObject *itmTuple = Py_BuildValue("(ssskk)", itm->URI.c_str(), + PyObject *itmTuple = Py_BuildValue("(sssNN)", itm->URI.c_str(), itm->Description.c_str(), itm->ShortDesc.c_str(), - worker->TotalSize, - worker->CurrentSize); + MkPyNumber(worker->TotalSize), + MkPyNumber(worker->CurrentSize)); PyTuple_SetItem(itemsTuple, tuplePos, itmTuple); } diff --git a/python/string.cc b/python/string.cc index a5016103..7abe2d17 100644 --- a/python/string.cc +++ b/python/string.cc @@ -91,7 +91,7 @@ PyObject *StrStringToBool(PyObject *Self,PyObject *Args) char *Str = 0; if (PyArg_ParseTuple(Args,"s",&Str) == 0) return 0; - return Py_BuildValue("i",StringToBool(Str)); + return MkPyNumber(StringToBool(Str)); } PyObject *StrStrToTime(PyObject *Self,PyObject *Args) @@ -107,7 +107,7 @@ PyObject *StrStrToTime(PyObject *Self,PyObject *Args) return Py_None; } - return Py_BuildValue("i",Result); + return MkPyNumber(Result); } PyObject *StrCheckDomainList(PyObject *Self,PyObject *Args) diff --git a/python/tag.cc b/python/tag.cc index 44cd06af..94554400 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -247,7 +247,7 @@ static PyObject *TagSecBytes(PyObject *Self,PyObject *Args) if (PyArg_ParseTuple(Args,"") == 0) return 0; - return Py_BuildValue("i",GetCpp(Self).size()); + return MkPyNumber(GetCpp(Self).size()); } static PyObject *TagSecStr(PyObject *Self) @@ -319,7 +319,8 @@ static PyObject *TagFileOffset(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - return Py_BuildValue("i",((TagFileData *)Self)->Object.Offset()); + return MkPyNumber(((TagFileData *)Self)->Object.Offset()); + } static char *doc_Jump = diff --git a/python/tarfile.cc b/python/tarfile.cc index 215d3a8c..cdfe0a7c 100644 --- a/python/tarfile.cc +++ b/python/tarfile.cc @@ -189,35 +189,35 @@ static PyObject *tarmember_get_linkname(PyObject *self, void *closure) static PyObject *tarmember_get_mode(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self).Mode); + return MkPyNumber(GetCpp(self).Mode); } static PyObject *tarmember_get_uid(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self).UID); + return MkPyNumber(GetCpp(self).UID); } static PyObject *tarmember_get_gid(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self).GID); + return MkPyNumber(GetCpp(self).GID); } static PyObject *tarmember_get_size(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self).Size); + return MkPyNumber(GetCpp(self).Size); } static PyObject *tarmember_get_mtime(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self).MTime); + return MkPyNumber(GetCpp(self).MTime); } static PyObject *tarmember_get_major(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self).Major); + return MkPyNumber(GetCpp(self).Major); } static PyObject *tarmember_get_minor(PyObject *self, void *closure) { - return Py_BuildValue("k", GetCpp(self).Minor); + return MkPyNumber(GetCpp(self).Minor); } static PyObject *tarmember_repr(PyObject *self) -- cgit v1.2.3 From 16166e89fb1d1243ac92017f03d7bdada904cd38 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 21 Apr 2011 14:21:22 +0200 Subject: apt_pkg: Add apt_pkg.Version.multi_arch and friends --- debian/changelog | 3 +++ doc/source/library/apt_pkg.rst | 43 ++++++++++++++++++++++++++++++++++++++++++ python/apt_pkgmodule.cc | 14 ++++++++++++++ python/cache.cc | 8 ++++++++ 4 files changed, 68 insertions(+) (limited to 'python') diff --git a/debian/changelog b/debian/changelog index c2377956..3b2a739a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,9 @@ python-apt (0.8.0~exp3) UNRELEASED; urgency=low [ Stéphane Graber ] * Update enable_component to also apply to -src entries (LP: #758732) + + [ Julian Andres Klode ] + * apt_pkg: Add apt_pkg.Version.multi_arch and friends -- Julian Andres Klode Tue, 12 Apr 2011 17:19:49 +0200 diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst index 72ca5ecc..28914395 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -758,6 +758,49 @@ Example: .. attribute:: installed_size The size of the package (in kilobytes), when unpacked on the disk. + + .. attribute:: multi_arch + + The multi-arch state of the package. Can be one of the following + attributes. + + .. attribute:: MULTI_ARCH_NONE + + No multi-arch + + .. attribute:: MULTI_ARCH_ALL + + An ``Architecture: all`` package + + + .. attribute:: MULTI_ARCH_FOREIGN + + Can satisfy dependencies of foreign-architecture + packages + + .. attribute:: MULTI_ARCH_ALL_FOREIGN + + :attr:`MULTI_ARCH_FOREIGN` for ``Architecture: all`` + packages. + + .. attribute:: MULTI_ARCH_SAME + + Multiple versions from different architectures may be + installed in parallel, but may only satisfy dependencies + of packages from the same architecture + + .. attribute:: MULTI_ARCH_ALLOWED + + Installation in parallel and satisfying ``pkg:any`` + style dependencies is allowed. + + .. attribute:: MULTI_ARCH_ALL_ALLOWED + + :attr:`MULTI_ARCH_ALLOWED` for ``Architecture: all`` + packages. + + + .. attribute:: parent_pkg diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 2394b0f8..a8b8d2f4 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -905,6 +905,20 @@ extern "C" void initapt_pkg() MkPyNumber(pkgPackageManager::Incomplete)); #endif + PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_NONE", + MkPyNumber(pkgCache::Version::None)); + PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL", + MkPyNumber(pkgCache::Version::All)); + PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_FOREIGN", + MkPyNumber(pkgCache::Version::Foreign)); + PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_SAME", + MkPyNumber(pkgCache::Version::Same)); + PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALLOWED", + MkPyNumber(pkgCache::Version::Allowed)); + PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_FOREIGN", + MkPyNumber(pkgCache::Version::AllForeign)); + PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_ALLOWED", + MkPyNumber(pkgCache::Version::AllAllowed)); // AcquireItem Constants. PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_IDLE", MkPyNumber(pkgAcquire::Item::StatIdle)); diff --git a/python/cache.cc b/python/cache.cc index 160fd208..b263d320 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -1047,6 +1047,11 @@ static PyObject *VersionGetTranslatedDescription(PyObject *Self, void*) { Ver.TranslatedDescription()); } +static PyObject *VersionGetMultiArch(PyObject *Self, void*) +{ + return MkPyNumber(Version_GetVer(Self)->MultiArch); +} + #if 0 // FIXME: enable once pkgSourceList is stored somewhere static PyObject *VersionGetIsTrusted(PyObject *Self, void*) { else if (strcmp("IsTrusted", Name) == 0) @@ -1122,6 +1127,9 @@ static PyGetSetDef VersionGetSet[] = { "The numeric ID of the package."}, {"installed_size",VersionGetInstalledSize,0, "The installed size of this package version."}, + {"multi_arch",VersionGetMultiArch,0, + "Multi-arch state of this package, as an integer. See\n" + "the various MULTI_ARCH_* members."}, {"parent_pkg",VersionGetParentPkg,0, "The parent package of this version."}, {"priority",VersionGetPriority,0, -- cgit v1.2.3 From 6282a925c2e32aeaa342b789470a01b6dcf70890 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 27 Apr 2011 13:08:20 +0200 Subject: apt_pkg: Add OrderList, wanted for mancoosi (Closes: #623485) --- debian/changelog | 6 + doc/source/c++/api.rst | 28 ++++ doc/source/library/apt_pkg.rst | 93 ++++++++++++ doc/source/whatsnew/0.8.0.rst | 2 + python/apt_pkgmodule.cc | 18 ++- python/apt_pkgmodule.h | 3 + python/orderlist.cc | 317 +++++++++++++++++++++++++++++++++++++++++ python/python-apt-helpers.cc | 1 + python/python-apt.h | 8 ++ setup.py | 2 +- 10 files changed, 476 insertions(+), 2 deletions(-) create mode 100644 python/orderlist.cc (limited to 'python') diff --git a/debian/changelog b/debian/changelog index 702a69d4..ab1839d2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +python-apt (0.8.0~exp4) UNRELEASED; urgency=low + + * apt_pkg: Add OrderList, wanted for mancoosi (Closes: #623485) + + -- Julian Andres Klode Wed, 27 Apr 2011 12:55:59 +0200 + python-apt (0.8.0~exp3) experimental; urgency=low [ Stéphane Graber ] diff --git a/doc/source/c++/api.rst b/doc/source/c++/api.rst index 25cfcd9e..63ed1599 100644 --- a/doc/source/c++/api.rst +++ b/doc/source/c++/api.rst @@ -622,6 +622,34 @@ IndexFile (pkgIndexFile) Return the :ctype:`pkgIndexFile` pointer contained in the Python object *object*. +OrderList (pkgOrderList) +--------------------------- +.. cvar:: PyTypeObject PyOrderList_Type + + The type object for :class:`apt_pkg.OrderList` objects. + +.. cfunction:: int PyOrderList_Check(PyObject *object) + + Check that the object *object* is an :class:`apt_pkg.OrderList` object, or + a subclass thereof. + +.. cfunction:: int PyOrderList_CheckExact(PyObject *object) + + Check that the object *object* is an :class:`apt_pkg.OrderList` object + and no subclass thereof. + +.. cfunction:: PyObject* PyOrderList_FromCpp(pkgOrderList *cpp, bool delete, PyObject *owner) + + Create a new :class:`apt_pkg.OrderList` object from the :ctype:`pkgOrderList` + pointer given by the parameter *cpp*. If the parameter *delete* is + true, the object pointed to by *cpp* will be deleted when the reference + count of the returned object reaches 0. The owner must be a + :class:`apt_pkg.DepCache` object. + +.. cfunction:: pkgOrderList* PyOrderList_ToCpp(PyObject *object) + + Return the :ctype:`pkgOrderList` pointer contained in the Python object + *object*. PackageManager (pkgPackageManager) ---------------------------------- diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst index 28914395..fce4f804 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -422,6 +422,99 @@ Installing with :class:`PackageManager` A constant for checking whether the the result of the call to :meth:`do_install` is 'incomplete'. + +Installation ordering with :class:`OrderList` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. class:: OrderList(depcache: DepCache) + + Represent a :ctype:`pkgOrderList`, used for installation + ordering. This class provides several methods and attributes, + is complicated and should not be used by normal programs. + + .. versionadded:: 0.8.0 + + This class is a sequence and supports the following operations: + + .. describe:: list[index] + + Get the package at the given index in the list. Negative + index is supported. + + .. describe:: len(list) + + The length of the list. + + It also supports the append() method from :class:`list`: + + .. method:: append(pkg: Package) + + Append a new package to the end of the list. Please note that + you may not append a package twice, as only as much packages + as in the cache can be added. + + The class also defines several specific attributes and methods, + to be described hereinafter. + + .. method:: score(pkg: Package) + + Return the score of the package. Packages are basically + ordered by descending score. + + This class allows flags to be set on packages. Those flags are: + + .. attribute:: FLAG_ADDED + .. attribute:: FLAG_ADD_PENDING + .. attribute:: FLAG_IMMEDIATE + .. attribute:: FLAG_LOOP + .. attribute:: FLAG_UNPACKED + .. attribute:: FLAG_CONFIGURED + .. attribute:: FLAG_REMOVED + .. attribute:: FLAG_STATES_MASK + + Same as ``FLAG_UNPACKED | FLAG_CONFIGURED | FLAG_REMOVED`` + + .. attribute:: FLAG_IN_LIST + .. attribute:: FLAG_AFTER + + The methods to work with those flags are: + + .. method:: flag(pkg: Package, flag: int[, unset_flags: int]) + + Flag a package. Sets the flags given in *flag* and unsets + any flags given in *unset_flags*. + + .. method:: is_flag(pkg: Package, flag: int) + + Check whether the flags in *flag* are set for the package. + + .. method:: wipe_flags(flags: int) + + Remove the flags in *flags* from all packages. + + .. method:: is_missing(pkg: Package) + + Check if the package is missing (not really usable right now) + + .. method:: is_now(pkg: Package) + + Check if the package is flagged for any state but removal. + + The following methods for ordering are provided: + + .. method:: order_critical() + + Order the packages for critical unpacking; that is, only + respect pre-dependencies. + + .. method:: order_unpack() + + Order the packages for unpacking, repecting Pre-Depends and + Conflicts. + + .. method:: order_configure() + + Order the packages for configuration, respecting Depends. Improve performance with :class:`ActionGroup` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/source/whatsnew/0.8.0.rst b/doc/source/whatsnew/0.8.0.rst index fda53443..fa58a022 100644 --- a/doc/source/whatsnew/0.8.0.rst +++ b/doc/source/whatsnew/0.8.0.rst @@ -23,6 +23,8 @@ This release of python-apt also features several other, smaller changes: * apt_pkg.Cache() now takes None for the progress parameter, preventing progress reporting. + * A new class :class:`apt_pkg.OrderList` has been added on request + of the mancoosi project. There have been various other changes, see the changelog for a complete list of changes. diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index a8b8d2f4..139ff016 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -734,7 +735,10 @@ static struct _PyAptPkgAPIStruct API = { &PyVersion_ToCpp, // version_tocpp &PyGroup_Type, // group_type &PyGroup_FromCpp, // group_fromcpp - &PyGroup_ToCpp // group_tocpp + &PyGroup_ToCpp, // group_tocpp + &PyOrderList_Type, // orderlist_type + &PyOrderList_FromCpp, // orderlist_fromcpp + &PyOrderList_ToCpp // orderlist_tocpp }; @@ -843,6 +847,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"AcquireItemDesc",&PyAcquireItemDesc_Type); ADDTYPE(Module,"SystemLock",&PySystemLock_Type); ADDTYPE(Module,"FileLock",&PyFileLock_Type); + ADDTYPE(Module,"OrderList",&PyOrderList_Type); // Tag file constants PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", CharCharToList(TFRewritePackageOrder)); @@ -850,6 +855,16 @@ extern "C" void initapt_pkg() PyModule_AddObject(Module,"REWRITE_SOURCE_ORDER", CharCharToList(TFRewriteSourceOrder)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADDED", MkPyNumber(pkgOrderList::Added)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADD_PENDIG", MkPyNumber(pkgOrderList::AddPending)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IMMEDIATE", MkPyNumber(pkgOrderList::Immediate)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_LOOP", MkPyNumber(pkgOrderList::Loop)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_UNPACKED", MkPyNumber(pkgOrderList::UnPacked)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_CONFIGURED", MkPyNumber(pkgOrderList::Configured)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_REMOVED", MkPyNumber(pkgOrderList::Removed)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IN_LIST", MkPyNumber(pkgOrderList::InList)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_AFTER", MkPyNumber(pkgOrderList::After)); + PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_STATES_MASK", MkPyNumber(pkgOrderList::States)); // Acquire constants. // some constants @@ -983,6 +998,7 @@ extern "C" void initapt_pkg() PyModule_AddIntConstant(Module,"INSTSTATE_HOLD",pkgCache::State::Hold); PyModule_AddIntConstant(Module,"INSTSTATE_HOLD_REINSTREQ",pkgCache::State::HoldReInstReq); + // DEPRECATED API #ifdef COMPAT_0_7 PyModule_AddObject(Module,"RewritePackageOrder", diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 7a04204c..89179551 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -134,6 +134,7 @@ extern PyTypeObject PyAcquireItemDesc_Type; extern PyTypeObject PyAcquireWorker_Type; extern PyTypeObject PySystemLock_Type; extern PyTypeObject PyFileLock_Type; +extern PyTypeObject PyOrderList_Type; // Functions to be exported in the public API. @@ -159,6 +160,7 @@ extern PyTypeObject PyFileLock_Type; # define PyPackage_ToCpp GetCpp # define PyPackageFile_ToCpp GetCpp # define PyIndexFile_ToCpp GetCpp +# define PyOrderList_ToCpp GetCpp # define PyPackageList_ToCpp GetCpp // TODO # define PyPackageManager_ToCpp GetCpp # define PyPackageRecords_ToCpp GetCpp // TODO @@ -191,6 +193,7 @@ PyObject* PyMetaIndex_FromCpp(metaIndex* const &obj, bool Delete, PyObject *Owne PyObject* PyPackage_FromCpp(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner); PyObject* PyGroup_FromCpp(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner); PyObject* PyIndexFile_FromCpp(pkgIndexFile* const &obj, bool Delete, PyObject *Owner); +PyObject* PyOrderList_FromCpp(pkgOrderList* const &obj, bool Delete, PyObject *Owner); PyObject* PyPackageFile_FromCpp(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner); //PyObject* PyPackageList_FromCpp(PkgListStruct const &obj, bool Delete, PyObject *Owner); PyObject* PyPackageManager_FromCpp(pkgPackageManager* const &obj, bool Delete, PyObject *Owner); diff --git a/python/orderlist.cc b/python/orderlist.cc new file mode 100644 index 00000000..9fbed5f2 --- /dev/null +++ b/python/orderlist.cc @@ -0,0 +1,317 @@ +/* + * orderlist.cc - Wrapper around pkgOrderList + * + * Copyright 2011 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include "apt_pkgmodule.h" +#include "generic.h" +#include + +struct PyOrderList : CppPyObject { + pkgCache::PkgIterator current; + int nextIndex; +}; + +static PyObject *order_list_new(PyTypeObject *type,PyObject *args, + PyObject *kwds) +{ + PyObject *pyDepCache = NULL; + char *kwlist[] = {"depcache", NULL}; + if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, + &PyDepCache_Type, &pyDepCache) + == 0) + return 0; + + pkgDepCache *depCache = PyDepCache_ToCpp(pyDepCache); + return PyOrderList_FromCpp(new pkgOrderList(depCache), true, + pyDepCache); +} + +static const char order_list_append_doc[] = + "append(pkg: Package)\n\n" + "Append a package to the end of the list."; +static PyObject *order_list_append(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + PyObject *pyPackage = NULL; + if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0) + return 0; + + list->push_back(PyPackage_ToCpp(pyPackage)); + Py_RETURN_NONE; +} + +static const char order_list_score_doc[] = + "score(pkg: Package) -> int\n\n" + "Return the score of the package."; +static PyObject *order_list_score(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + PyObject *pyPackage = NULL; + if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0) + return 0; + + return MkPyNumber(list->Score(PyPackage_ToCpp(pyPackage))); +} + +static const char order_list_order_critical_doc[] = + "order_critical()\n\n" + "Order by PreDepends only (critical unpack order)."; +static PyObject *order_list_order_critical(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + if (PyArg_ParseTuple(args, "") == 0) + return 0; + + list->OrderCritical(); + + Py_INCREF(Py_None); + return HandleErrors(Py_None); +} + +static const char order_list_order_unpack_doc[] = + "order_unpack()\n\n" + "Order the packages for unpacking (see Debian Policy)."; +static PyObject *order_list_order_unpack(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + if (PyArg_ParseTuple(args, "") == 0) + return 0; + + list->OrderUnpack(); + Py_INCREF(Py_None); + return HandleErrors(Py_None); +} + +static const char order_list_order_configure_doc[] = + "order_configure()\n\n" + "Order the packages for configuration (see Debian Policy)."; +static PyObject *order_list_order_configure(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + if (PyArg_ParseTuple(args, "") == 0) + return 0; + + list->OrderConfigure(); + + Py_INCREF(Py_None); + return HandleErrors(Py_None); +} + +static bool valid_flags(unsigned int flags) { + return (flags & ~pkgOrderList::Added + & ~pkgOrderList::AddPending + & ~pkgOrderList::Immediate + & ~pkgOrderList::Loop + & ~pkgOrderList::UnPacked + & ~pkgOrderList::Configured + & ~pkgOrderList::Removed + & ~pkgOrderList::InList + & ~pkgOrderList::After + & ~pkgOrderList::States) == 0; +} + +static const char order_list_flag_doc[] = + "flag(pkg: Package, flag: int[, unset_flags: int])\n\n" + "Flag the package, set flags in 'flag' and remove flags in\n" + "'unset_flags'."; +static PyObject *order_list_flag(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + + PyObject *pyPkg = NULL; + unsigned int flags = 0; + unsigned int unset_flags = 0; + if (PyArg_ParseTuple(args, "O!I|I", &PyPackage_Type, &pyPkg, + &flags, &unset_flags) == 0) + return 0; + + if (!valid_flags(flags)) + return PyErr_Format(PyExc_ValueError, "flags (%u) is" + " not a valid combination of flags.", + flags); + if (!valid_flags(unset_flags)) + return PyErr_Format(PyExc_ValueError, "unset_flags (%u) is" + " not a valid combination of flags.", + unset_flags); + + list->Flag(PyPackage_ToCpp(pyPkg), flags, unset_flags); + + Py_RETURN_NONE; +} + +static const char order_list_is_flag_doc[] = + "is_flag(pkg: Package, flag: int)\n\n" + "Check if the flag(s) are set."; +static PyObject *order_list_is_flag(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + PyObject *pyPkg = NULL; + unsigned int flags = 0; + if (PyArg_ParseTuple(args, "O!I", &PyPackage_Type, &pyPkg, + &flags) == 0) + return 0; + + if (!valid_flags(flags)) + return PyErr_Format(PyExc_ValueError, "flags (%u) is" + " not a valid combination of flags.", + flags); + + return PyBool_FromLong(list->IsFlag(PyPackage_ToCpp(pyPkg), flags)); +} + +static const char order_list_wipe_flags_doc[] = + "wipe_flags(flags: int)\n\n" + "Remove the flags in 'flags' from all packages in this list"; +static PyObject *order_list_wipe_flags(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + unsigned int flags = 0; + if (PyArg_ParseTuple(args, "I", &flags) == 0) + return 0; + + if (!valid_flags(flags)) + return PyErr_Format(PyExc_ValueError, "flags (%u) is" + " not a valid combination of flags.", + flags); + + list->WipeFlags(flags); + Py_RETURN_NONE; +} + +static const char order_list_is_now_doc[] = + "is_now(pkg: Package)\n\n" + "Check if the package is flagged for any state but removal."; +static PyObject *order_list_is_now(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + PyObject *pyPkg = NULL; + if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0) + return 0; + + return PyBool_FromLong(list->IsNow(PyPackage_ToCpp(pyPkg))); +} + +static const char order_list_is_missing_doc[] = + "is_now(pkg: Package)\n\n" + "Check if the package is marked for install."; +static PyObject *order_list_is_missing(PyObject *self,PyObject *args) +{ + pkgOrderList *list = GetCpp(self); + PyObject *pyPkg = NULL; + if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0) + return 0; + + return PyBool_FromLong(list->IsMissing(PyPackage_ToCpp(pyPkg))); +} + + +#define METHOD(name) {#name, order_list_##name, METH_VARARGS,\ + order_list_##name##_doc} + +static PyMethodDef order_list_methods[] = { + METHOD(append), + METHOD(score), + METHOD(order_critical), + METHOD(order_unpack), + METHOD(order_configure), + METHOD(flag), + METHOD(is_flag), + METHOD(is_now), + METHOD(is_missing), + METHOD(wipe_flags), + {} +}; + +static PyObject *order_list_seq_item(PyObject *self,Py_ssize_t index) +{ + pkgOrderList *list = GetCpp(self); + PyObject *owner = GetOwner(self); + PyObject *pycache = GetOwner(owner); + pkgCache *cache = PyCache_ToCpp(pycache); + + if (index < 0 || index >= list->size()) + return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index); + + return PyPackage_FromCpp(pkgCache::PkgIterator(*cache, + *(list->begin() + index)), + true, owner); +} + +Py_ssize_t order_list_seq_length(PyObject *self) +{ + return GetCpp(self)->size(); +} + +static PySequenceMethods order_list_as_sequence = +{ + order_list_seq_length, // sq_length + 0, // sq_concat + 0, // sq_repeat + order_list_seq_item, // sq_item + 0, // sq_ass_item + 0, // sq_contains + 0, // sq_inplace_concat + 0 // sq_inplace_repeat +}; + +static const char order_list_doc[] = "OrderList(depcache: DepCache)\n\n" + "Sequence type for packages with special ordering methods."; +PyTypeObject PyOrderList_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.OrderList", // tp_name + sizeof(CppPyObject), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDeallocPtr, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &order_list_as_sequence, // 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, // tp_flags + order_list_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + order_list_methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + order_list_new, // tp_new +}; diff --git a/python/python-apt-helpers.cc b/python/python-apt-helpers.cc index f50f62c4..079b93cf 100644 --- a/python/python-apt-helpers.cc +++ b/python/python-apt-helpers.cc @@ -54,6 +54,7 @@ NEW_FROM(PyMetaIndex_FromCpp,&PyMetaIndex_Type,metaIndex*) NEW_FROM(PyPackage_FromCpp,&PyPackage_Type,pkgCache::PkgIterator) NEW_FROM(PyGroup_FromCpp,&PyGroup_Type,pkgCache::GrpIterator) NEW_FROM(PyIndexFile_FromCpp,&PyIndexFile_Type,pkgIndexFile*) +NEW_FROM(PyOrderList_FromCpp,&PyOrderList_Type,pkgOrderList*) NEW_FROM(PyPackageFile_FromCpp,&PyPackageFile_Type,pkgCache::PkgFileIterator) //NEW_FROM(PyPackageList_FromCpp,&PyPackageList_Type,PkgListStruct) NEW_FROM(PyPackageManager_FromCpp,&PyPackageManager_Type,pkgPackageManager*) diff --git a/python/python-apt.h b/python/python-apt.h index ca8b557b..6f2a02df 100644 --- a/python/python-apt.h +++ b/python/python-apt.h @@ -170,6 +170,10 @@ struct _PyAptPkgAPIStruct { PyTypeObject *group_type; PyObject* (*group_fromcpp)(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner); pkgCache::GrpIterator& (*group_tocpp)(PyObject *self); + + PyTypeObject *orderlist_type; + PyObject* (*orderlist_fromcpp)(pkgOrderList* const &obj, bool Delete, PyObject *Owner); + pkgOrderList*& (*orderlist_tocpp)(PyObject *self); }; // Checking macros. @@ -228,6 +232,7 @@ struct _PyAptPkgAPIStruct { # define PyPackage_CheckExact(op) (op->op_type == &PyPackage_Type) # define PyPackageFile_CheckExact(op) (op->op_type == &PyPackageFile_Type) # define PyIndexFile_CheckExact(op) (op->op_type == &PyIndexFile_Type) +# define PyOrderList_CheckExact(op) (op->op_type == &PyOrderList_Type) # define PyPackageList_CheckExact(op) (op->op_type == &PyPackageList_Type) # define PyPackageManager_CheckExact(op) (op->op_type == &PyPackageManager_Type) # define PyPackageRecords_CheckExact(op) (op->op_type == &PyPackageRecords_Type) @@ -273,6 +278,7 @@ static int import_apt_pkg(void) { # define PyPackage_Type *(_PyAptPkg_API->package_type) # define PyPackageFile_Type *(_PyAptPkg_API->packagefile_type) # define PyIndexFile_Type *(_PyAptPkg_API->packageindexfile_type) +# define PyOrderList_Type *(_PyAptPkg_API->orderlist_type) # define PyPackageList_Type *(_PyAptPkg_API->packagelist_type) # define PyPackageManager_Type *(_PyAptPkg_API->packagemanager_type) # define PyPackageRecords_Type *(_PyAptPkg_API->packagerecords_type) @@ -306,6 +312,7 @@ static int import_apt_pkg(void) { # define PyPackage_ToCpp _PyAptPkg_API->package_tocpp # define PyPackageFile_ToCpp _PyAptPkg_API->packagefile_tocpp # define PyIndexFile_ToCpp _PyAptPkg_API->packageindexfile_tocpp +# define PyOrderList_ToCpp _PyAptPkg_API->orderlist_tocpp // NULL # define PyPackageList_ToCpp _PyAptPkg_API->packagelist_tocpp // NULL # define PyPackageManager_ToCpp _PyAptPkg_API->packagemanager_tocpp # define PyPackageRecords_ToCpp _PyAptPkg_API->packagerecords_tocpp @@ -339,6 +346,7 @@ static int import_apt_pkg(void) { # define PyPackage_FromCpp _PyAptPkg_API->package_fromcpp # define PyPackageFile_FromCpp _PyAptPkg_API->packagefile_fromcpp # define PyIndexFile_FromCpp _PyAptPkg_API->packageindexfile_fromcpp +# define PyOrderList_FromCpp _PyAptPkg_API->orderlist_fromcpp // NULL # define PyPackageList_FromCpp _PyAptPkg_API->packagelist_fromcpp // NULL # define PyPackageManager_FromCpp _PyAptPkg_API->packagemanager_fromcpp # define PyPackageRecords_FromCpp _PyAptPkg_API->packagerecords_fromcpp diff --git a/setup.py b/setup.py index 7f832673..eff78379 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', 'lock.cc', 'acquire-item.cc', 'python-apt-helpers.cc', - 'cachegroup.cc'] + 'cachegroup.cc', 'orderlist.cc'] files = sorted(['python/' + fname for fname in files], key=lambda s: s[:-3]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) -- cgit v1.2.3 From 750f432e42c605747d86826886c29b76d19269a3 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 29 Apr 2011 12:24:46 +0200 Subject: apt_pkg: Add subclassing fun to PackageManager, for #623485 as well --- debian/changelog | 1 + doc/source/library/apt_pkg.rst | 59 +++++++++ doc/source/whatsnew/0.8.0.rst | 12 +- python/apt_pkgmodule.cc | 3 +- python/apt_pkgmodule.h | 1 + python/pkgmanager.cc | 277 +++++++++++++++++++++++++++++++++++------ 6 files changed, 313 insertions(+), 40 deletions(-) (limited to 'python') diff --git a/debian/changelog b/debian/changelog index ff07fc21..b6f3da51 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ python-apt (0.8.0~exp4) UNRELEASED; urgency=low * apt_pkg: Add OrderList, wanted for mancoosi (Closes: #623485) + * apt_pkg: Add subclassing fun to PackageManager, for #623485 as well * apt.cache: Emit change signals in ProblemResolver * apt.Cache: Add a _changes_count member for later use diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst index fce4f804..81f2d408 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -423,6 +423,65 @@ Installing with :class:`PackageManager` A constant for checking whether the the result of the call to :meth:`do_install` is 'incomplete'. + All instances of this class also support the following methods: + + .. note:: + + This methods are provided mainly for subclassing purposes + and should not be used in most programs. This class is a + subclass of an internal :class:`_PackageManager` which does + not provide that methods. As the public C++ API creates such + an object without those methods, you should not rely on those + methods to be available unless you used the constructor of + :class:`PackageManager` to create the object. + + .. method:: configure(pkg: Package) -> bool + + Notify the package manager that the :class:`Package` given + by *pkg* is to be configured. Must return a ``True`` value + or ``None`` to continue, or a value which is ``False`` if + evaluated as boolean to abort. + + .. versionadded:: 0.8.0 + + .. method:: install(pkg: Package, filename: str) -> bool + + Notify the package manager that the :class:`Package` given + by *pkg* is to be installed from the .deb located at + *filename*. Must return a ``True`` value or ``None`` to + continue, or a value which is ``False`` if evaluated as + boolean to abort. + + + .. versionadded:: 0.8.0 + + .. method:: remove(pkg: Package, purge: bool) -> bool + + Notify the package manager that the :class:`Package` given + by *pkg* is to be removed. If *purge* is ``True``, the package + shall be purged. Must return a ``True`` value or ``None`` to + continue, or a value which is ``False`` if evaluated as boolean + to abort. + + + .. versionadded:: 0.8.0 + + .. method:: go(status_fd: int) -> bool + + Start dpkg, writing status information to the file descriptor + given by *status_fd*. Must return a ``True`` value or ``None`` to + continue, or a value which is ``False`` if evaluated as boolean + to abort. + + .. versionadded:: 0.8.0 + + .. method:: reset() + + Reset the package manager for a new round. + + .. versionadded:: 0.8.0 + + Installation ordering with :class:`OrderList` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/source/whatsnew/0.8.0.rst b/doc/source/whatsnew/0.8.0.rst index fa58a022..2eeb135e 100644 --- a/doc/source/whatsnew/0.8.0.rst +++ b/doc/source/whatsnew/0.8.0.rst @@ -16,6 +16,16 @@ This version of python-apt introduces multi-arch support: * A new class, :class:`apt_pkg.Group` has been added. * :class:`apt_pkg.Cache` can now be indexed by ``(name, architecture)`` tuples + +Features for mancoosi +---------------------- +Several new features related to ordering have been added on request +of the mancoosi project: + + * A new class :class:`apt_pkg.OrderList` has been added + * The :class:`apt_pkg.PackageManager` class now provides new methods + for registering install/remove/configure actions which can be + subclassed to check ordering. Other changes ------------- @@ -23,8 +33,6 @@ This release of python-apt also features several other, smaller changes: * apt_pkg.Cache() now takes None for the progress parameter, preventing progress reporting. - * A new class :class:`apt_pkg.OrderList` has been added on request - of the mancoosi project. There have been various other changes, see the changelog for a complete list of changes. diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 139ff016..e8490b4e 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -833,7 +833,8 @@ extern "C" void initapt_pkg() /* ========================= metaindex.cc ========================= */ ADDTYPE(Module,"MetaIndex",&PyMetaIndex_Type); // NO __new__() /* ========================= pkgmanager.cc ========================= */ - ADDTYPE(Module,"PackageManager",&PyPackageManager_Type); + ADDTYPE(Module,"_PackageManager",&PyPackageManager_Type); + ADDTYPE(Module,"PackageManager",&PyPackageManager2_Type); /* ========================= pkgrecords.cc ========================= */ ADDTYPE(Module,"PackageRecords",&PyPackageRecords_Type); /* ========================= pkgsrcrecords.cc ========================= */ diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 89179551..b3534a30 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -102,6 +102,7 @@ PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject *kwds); // packagemanager extern PyTypeObject PyPackageManager_Type; +extern PyTypeObject PyPackageManager2_Type; PyObject *GetPkgManager(PyObject *Self,PyObject *Args); diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index a65c88f8..b7bed658 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -17,36 +17,10 @@ #include #include #include +#include #include -static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) -{ - PyObject *Owner; - char *kwlist[] = {"depcache",0}; - if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type, - &Owner) == 0) - return 0; - - pkgPackageManager *pm = _system->CreatePM(GetCpp(Owner)); - - CppPyObject *PkgManagerObj = - CppPyObject_NEW(NULL, type,pm); - - return PkgManagerObj; -} - -#ifdef COMPAT_0_7 -PyObject *GetPkgManager(PyObject *Self,PyObject *Args) -{ - PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPackageManager() is " - "deprecated. Please see apt_pkg.PackageManager() for the " - "replacement.", 1); - return PkgManagerNew(&PyPackageManager_Type,Args,0); -} -#endif - - static PyObject *PkgManagerGetArchives(PyObject *Self,PyObject *Args) { pkgPackageManager *pm = GetCpp(Self); @@ -114,17 +88,16 @@ static PyMethodDef PkgManagerMethods[] = {} }; - static const char *packagemanager_doc = - "PackageManager(depcache: apt_pkg.DepCache)\n\n" - "PackageManager objects allow the fetching of packages marked for\n" - "installation and the installation of those packages. The parameter\n" - "'depcache' specifies an apt_pkg.DepCache object where information\n" - "about the package selections is retrieved from."; + "_PackageManager objects allow the fetching of packages marked for\n" + "installation and the installation of those packages.\n" + "This is an abstract base class that cannot be subclassed\n" + "in Python. The only subclass is apt_pkg.PackageManager. This\n" + "class is an implementation-detail and not part of the API."; PyTypeObject PyPackageManager_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.PackageManager", // tp_name + "apt_pkg._PackageManager", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods @@ -143,8 +116,7 @@ PyTypeObject PyPackageManager_Type = _PyAptObject_getattro, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_DEFAULT, // tp_flag, packagemanager_doc, // tp_doc 0, // tp_traverse 0, // tp_clear @@ -162,9 +134,240 @@ PyTypeObject PyPackageManager_Type = 0, // tp_dictoffset 0, // tp_init 0, // tp_alloc - PkgManagerNew, // tp_new + 0, // tp_new +}; + + +struct CppPyRef { + PyObject *o; + CppPyRef(const CppPyRef &o) { Py_XINCREF(o); this->o = o; } + CppPyRef(PyObject *o) : o(o) {} + ~CppPyRef() { Py_XDECREF(o); } + operator PyObject *() const { return o; } + PyObject *operator->() const { return o; } }; +class PyPkgManager : public pkgDPkgPM { + bool res(CppPyRef result) { + if (result == NULL) { + std::cerr << "Error in function: " << std::endl; + PyErr_Print(); + PyErr_Clear(); + return false; + } + return (result != NULL && + (result == Py_None || PyObject_IsTrue(result) == 1)); + } + + + PyObject *GetPyPkg(const PkgIterator &Pkg) { + PyObject *depcache = NULL; + PyObject *cache = NULL; + + depcache = GetOwner(pyinst); + if (depcache != NULL && PyDepCache_Check(depcache)) + cache = GetOwner(depcache); + + return PyPackage_FromCpp(Pkg, true, cache); + } + + /* Call through to Python */ + virtual bool Install(PkgIterator Pkg,string File) { + return res(PyObject_CallMethod(pyinst, "install", "(NN)", + GetPyPkg(Pkg), + CppPyString(File))); + } + virtual bool Configure(PkgIterator Pkg) { + return res(PyObject_CallMethod(pyinst, "configure", "(N)", + GetPyPkg(Pkg))); + } + virtual bool Remove(PkgIterator Pkg,bool Purge = false) { + return res(PyObject_CallMethod(pyinst, "remove", "(NN)", + GetPyPkg(Pkg), + PyBool_FromLong(Purge))); + } + virtual bool Go(int StatusFd=-1) { + return res(PyObject_CallMethod(pyinst, "go", "(i)", + StatusFd)); + } + virtual void Reset() { + CppPyRef(PyObject_CallMethod(pyinst, "reset", NULL)); + } + +public: + /* Those call the protected functions from the parent class */ + bool callInstall(PkgIterator Pkg,string File) { return pkgDPkgPM::Install(Pkg, File); } + bool callRemove(PkgIterator Pkg, bool Purge) { return pkgDPkgPM::Remove(Pkg, Purge); } + bool callGo(int StatusFd=-1) { return pkgDPkgPM::Go(StatusFd); } + void callReset() { return pkgDPkgPM::Reset(); } + bool callConfigure(PkgIterator Pkg) { return pkgDPkgPM::Configure(Pkg); } + pkgOrderList *getOrderList() { return pkgPackageManager::List; } + + PyPkgManager(pkgDepCache *Cache) : pkgDPkgPM(Cache) {}; + PyObject *pyinst; +}; + +static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) +{ + PyObject *Owner; + char *kwlist[] = {"depcache",0}; + if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type, + &Owner) == 0) + return 0; + + PyPkgManager *pm = new PyPkgManager(GetCpp(Owner)); + + CppPyObject *PkgManagerObj = + CppPyObject_NEW(NULL, type,pm); + + pm->pyinst = PkgManagerObj; + + return PkgManagerObj; +} + +#ifdef COMPAT_0_7 +PyObject *GetPkgManager(PyObject *Self,PyObject *Args) +{ + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPackageManager() is " + "deprecated. Please see apt_pkg.PackageManager() for the " + "replacement.", 1); + return PkgManagerNew(&PyPackageManager2_Type,Args,0); +} +#endif + +static PyObject *PkgManagerInstall(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp(Self); + PyObject *pkg; + const char *file; + + if (PyArg_ParseTuple(Args, "O!s", &PyPackage_Type,&pkg, &file) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callInstall(PyPackage_ToCpp(pkg), file))); +} + + +static PyObject *PkgManagerConfigure(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp(Self); + PyObject *pkg; + + if (PyArg_ParseTuple(Args, "O!", &PyPackage_Type,&pkg) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callConfigure(PyPackage_ToCpp(pkg)))); +} + +static PyObject *PkgManagerRemove(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp(Self); + PyObject *pkg; + char purge; + + if (PyArg_ParseTuple(Args, "O!b", &PyPackage_Type,&pkg, &purge) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callRemove(PyPackage_ToCpp(pkg), purge))); +} + +static PyObject *PkgManagerGo(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp(Self); + int fd; + + if (PyArg_ParseTuple(Args, "i", &fd) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callGo(fd))); +} + +static PyObject *PkgManagerReset(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp(Self); + + pm->callReset(); + Py_INCREF(Py_None); + return HandleErrors(Py_None); +} + +static PyMethodDef PkgManager2Methods[] = +{ + {"install",PkgManagerInstall,METH_VARARGS, + "install(pkg: Package, filename: str) -> bool \n\n" + "Add a install action. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"configure",PkgManagerConfigure,METH_VARARGS, + "configure(pkg: Package) -> bool \n\n" + "Add a configure action. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"remove",PkgManagerRemove,METH_VARARGS, + "remove(pkg: Package, purge: bool) -> bool \n\n" + "Add a removal action. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"go",PkgManagerGo,METH_VARARGS, + "go(status_fd: int) -> bool \n\n" + "Start dpkg. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"reset",PkgManagerReset,METH_VARARGS, + "reset()\n\n" + "Reset the package manager for a new round.\n" + "Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {} +}; + +static const char *packagemanager2_doc = + "PackageManager(depcache: apt_pkg.DepCache)\n\n" + "PackageManager objects allow the fetching of packages marked for\n" + "installation and the installation of those packages. The parameter\n" + "'depcache' specifies an apt_pkg.DepCache object where information\n" + "about the package selections is retrieved from.\n\n" + "Methods in this class can be overriden in sub classes\n" + "to implement behavior different from APT's dpkg implementation."; +PyTypeObject PyPackageManager2_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageManager", // tp_name + sizeof(CppPyObject), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDeallocPtr, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // 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 | // tp_flags + Py_TPFLAGS_BASETYPE), + packagemanager2_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + PkgManager2Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + &PyPackageManager_Type, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + PkgManagerNew, // tp_new +}; /*}}}*/ -- cgit v1.2.3 From ab08c42c90e9aab009b6d5f1b4bdce0c68300fa5 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 27 May 2011 16:06:22 +0200 Subject: Fix spelling errors reported by Lintian (sep[a->e]rated, overrid[d]en) --- debian/changelog | 1 + doc/source/library/apt.progress.base.rst | 6 +++--- doc/source/library/apt_pkg.rst | 2 +- python/cdrom.cc | 2 +- python/pkgmanager.cc | 12 ++++++------ 5 files changed, 12 insertions(+), 11 deletions(-) (limited to 'python') diff --git a/debian/changelog b/debian/changelog index 85cd3166..53830d98 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,7 @@ python-apt (0.8.0~exp5) UNRELEASED; urgency=low * utils/get_debian_mirrors.py: Adjust for new Alioth SCM urls * debian/control: Standards-Version 3.9.2 * Fix Lintian overrides + * Fix spelling errors reported by Lintian (sep[a->e]rated, overrid[d]en) [ Tshepang Lekhonkhobe ] * Fix get_changelog in Python 3 (Closes: #626532) diff --git a/doc/source/library/apt.progress.base.rst b/doc/source/library/apt.progress.base.rst index 3fd2a7a0..22006f77 100644 --- a/doc/source/library/apt.progress.base.rst +++ b/doc/source/library/apt.progress.base.rst @@ -233,7 +233,7 @@ InstallProgress (Abstract) Called when a error is detected during the install. - The following method should be overriden to implement progress reporting + The following method should be overridden to implement progress reporting for dpkg-based runs i.e. calls to :meth:`run` with a filename: .. method:: processing(pkg, stage) @@ -252,7 +252,7 @@ InstallProgress file (:file:`/var/lib/dpkg/status`) and documented in :manpage:`dpkg(1)`. - The following methods should be overriden to implement progress reporting + The following methods should be overridden to implement progress reporting for :meth:`run` calls with an :class:`apt_pkg.PackageManager` object as their parameter: @@ -274,7 +274,7 @@ InstallProgress This method is called when all changes have been applied. There are also several methods which are fully implemented and should not - be overriden by subclasses unless the subclass has very special needs: + be overridden by subclasses unless the subclass has very special needs: .. method:: fork() -> int diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst index 81f2d408..ffef9c50 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -45,7 +45,7 @@ Working with the cache .. note:: - The cache supports colon-seperated name:architecture pairs. For + The cache supports colon-separated name:architecture pairs. For normal architectures, they are equal to a (name, architecture) tuple. For the the "any" architecture behavior is different, as "name:any" is equivalent to ("name:any", "any"). This is done so diff --git a/python/cdrom.cc b/python/cdrom.cc index 7f89e9d3..6ac16d59 100644 --- a/python/cdrom.cc +++ b/python/cdrom.cc @@ -52,7 +52,7 @@ static PyObject *cdrom_add(PyObject *Self,PyObject *Args) static char *cdrom_ident_doc = "ident(progress: apt_pkg.CdromProgress) -> str\n\n" "Try to identify the CD-ROM and if successful return the hexadecimal\n" - "CDROM-ID (and a integer version suffix seperated by -) as a\n" + "CDROM-ID (and a integer version suffix separated by -) as a\n" "string. Otherwise, return None or raise an error.\n\n" "The ID is created by hashing all file and directory names on the\n" "CD-ROM and appending the version."; diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index b7bed658..f51dbbbc 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -295,24 +295,24 @@ static PyMethodDef PkgManager2Methods[] = { {"install",PkgManagerInstall,METH_VARARGS, "install(pkg: Package, filename: str) -> bool \n\n" - "Add a install action. Can be overriden in subclasses.\n\n" + "Add a install action. Can be overridden in subclasses.\n\n" "New in version 0.8.0."}, {"configure",PkgManagerConfigure,METH_VARARGS, "configure(pkg: Package) -> bool \n\n" - "Add a configure action. Can be overriden in subclasses.\n\n" + "Add a configure action. Can be overridden in subclasses.\n\n" "New in version 0.8.0."}, {"remove",PkgManagerRemove,METH_VARARGS, "remove(pkg: Package, purge: bool) -> bool \n\n" - "Add a removal action. Can be overriden in subclasses.\n\n" + "Add a removal action. Can be overridden in subclasses.\n\n" "New in version 0.8.0."}, {"go",PkgManagerGo,METH_VARARGS, "go(status_fd: int) -> bool \n\n" - "Start dpkg. Can be overriden in subclasses.\n\n" + "Start dpkg. Can be overridden in subclasses.\n\n" "New in version 0.8.0."}, {"reset",PkgManagerReset,METH_VARARGS, "reset()\n\n" "Reset the package manager for a new round.\n" - "Can be overriden in subclasses.\n\n" + "Can be overridden in subclasses.\n\n" "New in version 0.8.0."}, {} }; @@ -323,7 +323,7 @@ static const char *packagemanager2_doc = "installation and the installation of those packages. The parameter\n" "'depcache' specifies an apt_pkg.DepCache object where information\n" "about the package selections is retrieved from.\n\n" - "Methods in this class can be overriden in sub classes\n" + "Methods in this class can be overridden in sub classes\n" "to implement behavior different from APT's dpkg implementation."; PyTypeObject PyPackageManager2_Type = { -- cgit v1.2.3 From dad23d3d0cf1b15302c8fe1845a93f3d6de54ed7 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 13 Jul 2011 14:14:43 +0200 Subject: * python/arfile.cc: - use APT::Configuration::getCompressionTypes() instead of duplicating the supported methods here * tests/test_debfile.py: - add test for raise on unknown data.tar.xxx --- debian/changelog | 8 +++++ python/arfile.cc | 52 +++++++++++++++++++------------ tests/data/test_debs/data-tar-broken.deb | Bin 0 -> 626 bytes tests/test_debfile.py | 6 ++++ 4 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 tests/data/test_debs/data-tar-broken.deb (limited to 'python') diff --git a/debian/changelog b/debian/changelog index 6cd9a042..a25167d5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,14 @@ python-apt (0.8.1) UNRELEASED; urgency=low + [ Julian Andres Klode ] * Breaks: debsecan (<< 0.4.15) [not only << 0.4.14] (Closes: #629512) + + [ Michael Vogt ] + * python/arfile.cc: + - use APT::Configuration::getCompressionTypes() instead of duplicating + the supported methods here + * tests/test_debfile.py: + - add test for raise on unknown data.tar.xxx -- Julian Andres Klode Tue, 07 Jun 2011 14:00:22 +0200 diff --git a/python/arfile.cc b/python/arfile.cc index c3aa74d1..c31ea35e 100644 --- a/python/arfile.cc +++ b/python/arfile.cc @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -477,8 +479,8 @@ PyTypeObject PyArArchive_Type = { * Representation of a Debian package. * * This does not resemble debDebFile in apt-inst, but instead is a subclass - * of ArFile which adds properties for the control.tar.{xz,lzma,bz2,gz} and - * data.tar.{xz,lzma,bz2,gz} members which return TarFile objects. It also adds + * of ArFile which adds properties for the control.tar.$compression and + * data.tar.$compression members which return TarFile objects. It also adds * a descriptor 'version' which returns the content of 'debian-binary'. * * We are using it this way as it seems more natural to represent this special @@ -532,21 +534,28 @@ static PyObject *debfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return PyErr_Format(PyExc_SystemError, "No debian archive, missing %s", "control.tar.gz"); - self->data = _gettar(self, self->Object->FindMember("data.tar.gz"), - "gzip"); - if (!self->data) - self->data = _gettar(self, self->Object->FindMember("data.tar.bz2"), - "bzip2"); - if (!self->data) - self->data = _gettar(self, self->Object->FindMember("data.tar.lzma"), - "lzma"); - if (!self->data) - self->data = _gettar(self, self->Object->FindMember("data.tar.xz"), - "xz"); - if (!self->data) - return PyErr_Format(PyExc_SystemError, "No debian archive, missing %s", - "data.tar.gz or data.tar.bz2 or data.tar.lzma " - "or data.tar.xz"); + // try all compression types + std::vector types = APT::Configuration::getCompressionTypes(); + for (std::vector::const_iterator t = types.begin(); + t != types.end(); ++t) + { + string member = string("data.tar.").append(*t); + string comp = _config->Find(string("Acquire::CompressionTypes::").append(*t)); + self->data = _gettar(self, self->Object->FindMember(member.c_str()), + comp.c_str()); + if (self->data) + break; + } + // no data found, we need to + if (!self->data) { + string error; + for (std::vector::const_iterator t = types.begin(); + t != types.end(); ++t) + error.append(*t + ","); + return PyErr_Format(PyExc_SystemError, + "No debian archive, missing data.tar.{%s}", + error.c_str()); + } const ARArchive::Member *member = self->Object->FindMember("debian-binary"); @@ -590,7 +599,9 @@ static PyGetSetDef debfile_getset[] = { {"control",(getter)debfile_get_control,0, "The TarFile object associated with the control.tar.gz member."}, {"data",(getter)debfile_get_data,0, - "The TarFile object associated with the data.tar.{gz,bz2,lzma,xz}) member."}, + "The TarFile object associated with the data.tar.$compression member. " + "All apt compression methods are supported. " + }, {"debian_binary",(getter)debfile_get_debian_binary,0, "The package version, as contained in debian-binary."}, {NULL} @@ -604,8 +615,9 @@ static const char *debfile_doc = "specifying a file descriptor (returned by e.g. os.open()).\n" "The recommended way of using it is to pass in the path to the file.\n\n" "It differs from ArArchive by providing the members 'control', 'data'\n" - "and 'version' for accessing the control.tar.gz, data.tar.{gz,bz2,lzma,xz},\n" - "and debian-binary members in the archive."; + "and 'version' for accessing the control.tar.gz, data.tar.$compression \n" + "(all apt compression methods are supported), and debian-binary members \n" + "in the archive."; PyTypeObject PyDebFile_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) diff --git a/tests/data/test_debs/data-tar-broken.deb b/tests/data/test_debs/data-tar-broken.deb new file mode 100644 index 00000000..4fd42e0f Binary files /dev/null and b/tests/data/test_debs/data-tar-broken.deb differ diff --git a/tests/test_debfile.py b/tests/test_debfile.py index 5f6d1aa2..86a51cb9 100644 --- a/tests/test_debfile.py +++ b/tests/test_debfile.py @@ -119,6 +119,12 @@ Description: testpackage for gdebi - contains usr/bin/binary for file reading deb = apt.debfile.DebPackage("./data/test_debs/data-tar-xz.deb") self.assertEqual(deb.filelist, ["./", "usr/", "usr/bin/"]) + def test_no_supported_data_tar(self): + # ensure that a unknown data.tar.xxx raises a exception + with self.assertRaises(SystemError): + deb = apt.debfile.DebPackage("./data/test_debs/data-tar-broken.deb") + + if __name__ == "__main__": #logging.basicConfig(level=logging.DEBUG) -- cgit v1.2.3