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 --- tests/test_group.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/test_group.py (limited to 'tests') 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 'tests') 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 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 'tests') 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 82bd14484ffa3fbe0b68777402cb31000bd7dd22 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 6 Apr 2011 10:09:19 +0200 Subject: aptsources: Parse multi-arch sources.list files correctly --- aptsources/sourceslist.py | 24 ++++++++++++++++++++++-- debian/changelog | 6 ++++++ tests/data/aptsources/sources.list | 5 ++++- tests/test_aptsources.py | 19 +++++++++++++++++-- 4 files changed, 49 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py index 76bea43a..3cfe1791 100644 --- a/aptsources/sourceslist.py +++ b/aptsources/sourceslist.py @@ -81,6 +81,7 @@ class SourceEntry(object): self.invalid = False # is the source entry valid self.disabled = False # is it disabled ('#' in front) self.type = "" # what type (deb, deb-src) + self.architectures = [] # architectures self.uri = "" # base-uri self.dist = "" # distribution (dapper, edgy, etc) self.comps = [] # list of available componetns @@ -113,7 +114,7 @@ class SourceEntry(object): p_found = False space_found = False for i in range(len(line)): - if line[i] == "[": + if line[i] == "[" and not space_found: p_found=True tmp += line[i] elif line[i] == "]": @@ -169,6 +170,20 @@ class SourceEntry(object): if self.type not in ("deb", "deb-src", "rpm", "rpm-src"): self.invalid = True return + + if pieces[1].strip()[0] == "[": + options = pieces.pop(1).strip("[]").split(";") + for option in options: + try: + key, value = option.split("=", 1) + except Exception: + self.invalid = True + else: + if key == "arch": + self.architectures = value.split(",") + else: + self.invalid = True + # URI self.uri = pieces[1].strip() if len(self.uri) < 1: @@ -204,7 +219,12 @@ class SourceEntry(object): line = "" if self.disabled: line = "# " - line += "%s %s %s" % (self.type, self.uri, self.dist) + + line += self.type + + if self.architectures: + line += " [arch=%s]" % ",".join(self.architectures) + line += " %s %s" % (self.uri, self.dist) if len(self.comps) > 0: line += " " + " ".join(self.comps) if self.comment != "": diff --git a/debian/changelog b/debian/changelog index 6cad29e2..c942278d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +python-apt (0.8.0~exp2) UNRELEASED; urgency=low + + * aptsources: Parse multi-arch sources.list files correctly + + -- Julian Andres Klode Wed, 06 Apr 2011 09:46:52 +0200 + python-apt (0.8.0~exp1) experimental; urgency=low * Disable the old-style API, and break all packages using it diff --git a/tests/data/aptsources/sources.list b/tests/data/aptsources/sources.list index 5481d4f0..376d6961 100644 --- a/tests/data/aptsources/sources.list +++ b/tests/data/aptsources/sources.list @@ -3,4 +3,7 @@ deb http://de.archive.ubuntu.com/ubuntu/ edgy main # comment 2 deb http://de.archive.ubuntu.com/ubuntu/ edgy restricted # comment 3 -deb http://de.archive.ubuntu.com/ubuntu/ edgy universe \ No newline at end of file +deb http://de.archive.ubuntu.com/ubuntu/ edgy universe + +# multi-arch +deb [arch=amd64,i386] http://de.archive.ubuntu.com/ubuntu/ natty main diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py index 331df935..aeb2ce31 100644 --- a/tests/test_aptsources.py +++ b/tests/test_aptsources.py @@ -39,11 +39,11 @@ class TestAptSources(unittest.TestCase): apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") sources = aptsources.sourceslist.SourcesList(True, self.templates) - self.assertEqual(len(sources.list), 6) + self.assertEqual(len(sources.list), 9) # test load sources.list = [] sources.load("data/aptsources/sources.list") - self.assertEqual(len(sources.list), 6) + self.assertEqual(len(sources.list), 9) def testSourcesListAdding(self): """aptsources: Test additions to sources.list""" @@ -108,6 +108,21 @@ class TestAptSources(unittest.TestCase): if not s.template: self.fail("source entry '%s' has no matcher" % s) + def testMultiArch(self): + """aptsources: Test multi-arch parsing""" + + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" + "sources.list") + sources = aptsources.sourceslist.SourcesList(True, self.templates) + + assert sources.list[8].invalid == False + assert sources.list[8].type == "deb" + assert sources.list[8].architectures == ["amd64", "i386"] + assert sources.list[8].uri == "http://de.archive.ubuntu.com/ubuntu/" + assert sources.list[8].dist == "natty" + assert sources.list[8].comps == ["main"] + assert sources.list[8].line.strip() == str(sources.list[8]) + def testDistribution(self): """aptsources: Test distribution detection.""" apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" -- cgit v1.2.3 From 30a0dff267d9e99c25d5902e296fd115746e05c9 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 6 Apr 2011 10:22:53 +0200 Subject: aptsources: Allow insertion of new multi-arch entries --- aptsources/sourceslist.py | 17 +++++++++++++---- debian/changelog | 1 + tests/test_aptsources.py | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py index 3cfe1791..85db2de9 100644 --- a/aptsources/sourceslist.py +++ b/aptsources/sourceslist.py @@ -275,12 +275,14 @@ class SourcesList(object): yield entry raise StopIteration - def add(self, type, uri, dist, orig_comps, comment="", pos=-1, file=None): + def add(self, type, uri, dist, orig_comps, comment="", pos=-1, file=None, architectures=[]): """ Add a new source to the sources.list. The method will search for existing matching repos and will try to reuse them as far as possible """ + + architectures = set(architectures) # create a working copy of the component list so that # we can modify it later comps = orig_comps[:] @@ -288,7 +290,8 @@ class SourcesList(object): for source in self.list: if not source.disabled and not source.invalid and \ source.type == type and uri == source.uri and \ - source.dist == dist: + source.dist == dist and \ + set(source.architectures) == architectures: for new_comp in comps: if new_comp in source.comps: # we have this component already, delete it @@ -301,19 +304,25 @@ class SourcesList(object): # components if not source.disabled and not source.invalid and \ source.type == type and uri == source.uri and \ - source.dist == dist: + source.dist == dist and \ + set(source.architectures) == architectures: comps = uniq(source.comps + comps) source.comps = comps return source # if there is a corresponding repo which is disabled, enable it elif source.disabled and not source.invalid and \ source.type == type and uri == source.uri and \ + set(source.architectures) == architectures and \ source.dist == dist and \ len(set(source.comps) & set(comps)) == len(comps): source.disabled = False return source # there isn't any matching source, so create a new line and parse it - line = "%s %s %s" % (type, uri, dist) + + line = type + if architectures: + line += " [arch=%s]" % ",".join(architectures) + line += " %s %s" % (uri, dist) for c in comps: line = line + " " + c if comment != "": diff --git a/debian/changelog b/debian/changelog index c942278d..7ceda2ce 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ python-apt (0.8.0~exp2) UNRELEASED; urgency=low * aptsources: Parse multi-arch sources.list files correctly + * aptsources: Allow insertion of new multi-arch entries -- Julian Andres Klode Wed, 06 Apr 2011 09:46:52 +0200 diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py index aeb2ce31..1597674e 100644 --- a/tests/test_aptsources.py +++ b/tests/test_aptsources.py @@ -62,6 +62,14 @@ class TestAptSources(unittest.TestCase): "edgy", ["restricted"]) self.assertTrue(sources.list == before.list) + + before = copy.deepcopy(sources) + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", + "natty", + ["main"], architectures=["amd64", "i386"]) + self.assertTrue(sources.list == before.list) + + # test to add something new: multiverse sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", @@ -74,6 +82,34 @@ class TestAptSources(unittest.TestCase): "multiverse" in entry.comps): found = True self.assertTrue(found) + + # add a new natty entry without architecture specification + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", + "natty", + ["multiverse"]) + found = False + for entry in sources: + if (entry.type == "deb" and + entry.uri == "http://de.archive.ubuntu.com/ubuntu/" and + entry.dist == "natty" and + entry.architectures == [] and + "multiverse" in entry.comps): + found = True + self.assertTrue(found) + + # Add universe to existing multi-arch line + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", + "natty", + ["universe"], architectures=["i386", "amd64"]) + found = False + for entry in sources: + if (entry.type == "deb" and + entry.uri == "http://de.archive.ubuntu.com/ubuntu/" and + entry.dist == "natty" and + set(entry.architectures) == set(["amd64", "i386"]) and + set(entry.comps) == set(["main", "universe"])): + found = True + self.assertTrue(found) # test to add something new: multiverse *and* # something that is already there before = copy.deepcopy(sources) -- cgit v1.2.3 From 5ad927a38cad08a2d79f327e7bb3cc46316fa6a4 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 6 Apr 2011 11:15:47 +0200 Subject: all: Fix all instances of ResourceWarning about unclosed files --- apt/cache.py | 2 +- apt/cdrom.py | 7 +- apt/debfile.py | 2 +- apt/package.py | 12 ++-- aptsources/distinfo.py | 170 ++++++++++++++++++++++++---------------------- aptsources/sourceslist.py | 30 ++++---- debian/changelog | 1 + tests/test_apt_cache.py | 23 +++---- tests/test_hashes.py | 7 +- tests/test_progress.py | 3 +- 10 files changed, 134 insertions(+), 123 deletions(-) (limited to 'tests') diff --git a/apt/cache.py b/apt/cache.py index bfa41edc..3bbae923 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -107,7 +107,7 @@ class Cache(object): os.makedirs(rootdir + d) for f in files: if not os.path.exists(rootdir + f): - open(rootdir + f, "w") + open(rootdir + f, "w").close() def _run_callbacks(self, name): """ internal helper to run a callback """ diff --git a/apt/cdrom.py b/apt/cdrom.py index 01caa12f..9688de9e 100644 --- a/apt/cdrom.py +++ b/apt/cdrom.py @@ -79,9 +79,10 @@ class Cdrom(apt_pkg.Cdrom): src.append(apt_pkg.config.find_file("Dir::Etc::sourcelist")) # Check each file for fname in src: - for line in open(fname): - if not line.lstrip().startswith("#") and cd_id in line: - return True + with open(fname) as fobj: + for line in fobj: + if not line.lstrip().startswith("#") and cd_id in line: + return True return False if apt_pkg._COMPAT_0_7: diff --git a/apt/debfile.py b/apt/debfile.py index fb4312a1..d0f41def 100644 --- a/apt/debfile.py +++ b/apt/debfile.py @@ -64,7 +64,7 @@ class DebPackage(object): self._installed_conflicts = set() self._failure_string = "" self.filename = filename - self._debfile = apt_inst.DebFile(open(self.filename)) + self._debfile = apt_inst.DebFile(self.filename) control = self._debfile.control.extractdata("control") self._sections = apt_pkg.TagSection(control) self.pkgname = self._sections["Package"] diff --git a/apt/package.py b/apt/package.py index d7d5d167..54ef1c01 100644 --- a/apt/package.py +++ b/apt/package.py @@ -50,9 +50,9 @@ __all__ = ('BaseDependency', 'Dependency', 'Origin', 'Package', 'Record', def _file_is_same(path, size, md5): """Return ``True`` if the file is the same.""" - if (os.path.exists(path) and os.path.getsize(path) == size and - apt_pkg.md5sum(open(path)) == md5): - return True + if os.path.exists(path) and os.path.getsize(path) == size: + with open(path) as fobj: + return apt_pkg.md5sum(fobj) == md5 class FetchError(Exception): @@ -994,11 +994,8 @@ class Package(object): """ path = "/var/lib/dpkg/info/%s.list" % self.name try: - file_list = open(path, "rb") - try: + with open(path, "rb") as file_list: return file_list.read().decode("utf-8").split(u"\n") - finally: - file_list.close() except EnvironmentError: return [] @@ -1104,6 +1101,7 @@ class Package(object): # Check if the download was canceled if cancel_lock and cancel_lock.isSet(): return u"" + # FIXME: python3.2: Should be closed manually changelog_file = urllib2.urlopen(uri) # do only get the lines that are new changelog = u"" diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py index 6374f185..48a72719 100644 --- a/aptsources/distinfo.py +++ b/aptsources/distinfo.py @@ -176,89 +176,93 @@ class DistInfo(object): map_mirror_sets = {} dist_fname = "%s/%s.info" % (base_dir, dist) - dist_file = open(dist_fname) - if not dist_file: - return - template = None - component = None - for line in dist_file: - tokens = line.split(':', 1) - if len(tokens) < 2: - continue - field = tokens[0].strip() - value = tokens[1].strip() - if field == 'ChangelogURI': - self.changelogs_uri = _(value) - elif field == 'MetaReleaseURI': - self.metarelease_uri = value - elif field == 'Suite': - self.finish_template(template, component) - component=None - template = Template() - template.name = value - template.distribution = dist - template.match_name = "^%s$" % value - elif field == 'MatchName': - template.match_name = value - elif field == 'ParentSuite': - template.child = True - for nanny in self.templates: - # look for parent and add back ref to it - if nanny.name == value: - template.parents.append(nanny) - nanny.children.append(template) - elif field == 'Available': - template.available = apt_pkg.string_to_bool(value) - elif field == 'Official': - template.official = apt_pkg.string_to_bool(value) - elif field == 'RepositoryType': - template.type = value - elif field == 'BaseURI' and not template.base_uri: - template.base_uri = value - elif field == 'BaseURI-%s' % self.arch: - template.base_uri = value - elif field == 'MatchURI' and not template.match_uri: - template.match_uri = value - elif field == 'MatchURI-%s' % self.arch: - template.match_uri = value - elif (field == 'MirrorsFile' or - field == 'MirrorsFile-%s' % self.arch): - # Make the path absolute. - value = os.path.isabs(value) and value or \ - os.path.abspath(os.path.join(base_dir, value)) - if value not in map_mirror_sets: - mirror_set = {} - try: - mirror_data = filter(match_mirror_line.match, - [x.strip() for x in open(value)]) - except Exception: - print "WARNING: Failed to read mirror file" - mirror_data = [] - for line in mirror_data: - if line.startswith("#LOC:"): - location = match_loc.sub(r"\1", line) - continue - (proto, hostname, dir) = split_url(line) - if hostname in mirror_set: - mirror_set[hostname].add_repository(proto, dir) - else: - mirror_set[hostname] = Mirror( - proto, hostname, dir, location) - map_mirror_sets[value] = mirror_set - template.mirror_set = map_mirror_sets[value] - elif field == 'Description': - template.description = _(value) - elif field == 'Component': - if component and not template.has_component(component.name): - template.components.append(component) - component = Component(value) - elif field == 'CompDescription': - component.set_description(_(value)) - elif field == 'CompDescriptionLong': - component.set_description_long(_(value)) - self.finish_template(template, component) - template=None - component=None + with open(dist_fname) as dist_file: + + + + template = None + component = None + for line in dist_file: + tokens = line.split(':', 1) + if len(tokens) < 2: + continue + field = tokens[0].strip() + value = tokens[1].strip() + if field == 'ChangelogURI': + self.changelogs_uri = _(value) + elif field == 'MetaReleaseURI': + self.metarelease_uri = value + elif field == 'Suite': + self.finish_template(template, component) + component=None + template = Template() + template.name = value + template.distribution = dist + template.match_name = "^%s$" % value + elif field == 'MatchName': + template.match_name = value + elif field == 'ParentSuite': + template.child = True + for nanny in self.templates: + # look for parent and add back ref to it + if nanny.name == value: + template.parents.append(nanny) + nanny.children.append(template) + elif field == 'Available': + template.available = apt_pkg.string_to_bool(value) + elif field == 'Official': + template.official = apt_pkg.string_to_bool(value) + elif field == 'RepositoryType': + template.type = value + elif field == 'BaseURI' and not template.base_uri: + template.base_uri = value + elif field == 'BaseURI-%s' % self.arch: + template.base_uri = value + elif field == 'MatchURI' and not template.match_uri: + template.match_uri = value + elif field == 'MatchURI-%s' % self.arch: + template.match_uri = value + elif (field == 'MirrorsFile' or + field == 'MirrorsFile-%s' % self.arch): + # Make the path absolute. + value = os.path.isabs(value) and value or \ + os.path.abspath(os.path.join(base_dir, value)) + if value not in map_mirror_sets: + mirror_set = {} + try: + with open(value) as value_f: + mirror_data = filter(match_mirror_line.match, + [x.strip() for x in + value_f]) + except Exception: + print "WARNING: Failed to read mirror file" + mirror_data = [] + for line in mirror_data: + if line.startswith("#LOC:"): + location = match_loc.sub(r"\1", line) + continue + (proto, hostname, dir) = split_url(line) + if hostname in mirror_set: + mirror_set[hostname].add_repository(proto, dir) + else: + mirror_set[hostname] = Mirror( + proto, hostname, dir, location) + map_mirror_sets[value] = mirror_set + template.mirror_set = map_mirror_sets[value] + elif field == 'Description': + template.description = _(value) + elif field == 'Component': + if (component and not + template.has_component(component.name)): + template.components.append(component) + component = Component(value) + elif field == 'CompDescription': + component.set_description(_(value)) + elif field == 'CompDescriptionLong': + component.set_description_long(_(value)) + self.finish_template(template, component) + template=None + component=None def finish_template(self, template, component): " finish the current tempalte " diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py index 38831e9c..22770c10 100644 --- a/aptsources/sourceslist.py +++ b/aptsources/sourceslist.py @@ -368,15 +368,12 @@ class SourcesList(object): def load(self, file): """ (re)load the current sources """ try: - f = open(file, "r") - lines = f.readlines() - for line in lines: - source = SourceEntry(line, file) - self.list.append(source) + with open(file, "r") as f: + for line in f: + source = SourceEntry(line, file) + self.list.append(source) except: print "could not open file '%s'" % file - else: - f.close() def save(self): """ save the current sources """ @@ -388,14 +385,19 @@ class SourcesList(object): "## See sources.list(5) for more information, especialy\n" "# Remember that you can only use http, ftp or file URIs\n" "# CDROMs are managed through the apt-cdrom tool.\n") - open(path, "w").write(header) + + with open(path, "w") as f: + f.write(header) return - for source in self.list: - if source.file not in files: - files[source.file] = open(source.file, "w") - files[source.file].write(source.str()) - for f in files: - files[f].close() + + try: + for source in self.list: + if source.file not in files: + files[source.file] = open(source.file, "w") + files[source.file].write(source.str()) + finally: + for f in files: + files[f].close() def check_for_relations(self, sources_list): """get all parent and child channels in the sources list""" diff --git a/debian/changelog b/debian/changelog index 2864126a..cbe92343 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,7 @@ python-apt (0.8.0~exp2) UNRELEASED; urgency=low * aptsources: Parse multi-arch sources.list files correctly * aptsources: Allow insertion of new multi-arch entries * aptsources: Various cleanup work + * all: Fix all instances of ResourceWarning about unclosed files -- Julian Andres Klode Wed, 06 Apr 2011 09:46:52 +0200 diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py index b4cc650d..151a20e2 100644 --- a/tests/test_apt_cache.py +++ b/tests/test_apt_cache.py @@ -89,17 +89,17 @@ class TestAptCache(unittest.TestCase): tmpdir = tempfile.mkdtemp() dpkg_dir = os.path.join(tmpdir,"var","lib","dpkg") os.makedirs(os.path.join(dpkg_dir,"updates")) - open(os.path.join(dpkg_dir,"status"), "w") + open(os.path.join(dpkg_dir,"status"), "w").close() apt_pkg.config.set("Dir::State::status", os.path.join(dpkg_dir,"status")) cache = apt.Cache() # test empty self.assertFalse(cache.dpkg_journal_dirty) # that is ok, only [0-9] are dpkg jounral entries - open(os.path.join(dpkg_dir,"updates","xxx"), "w") + open(os.path.join(dpkg_dir,"updates","xxx"), "w").close() self.assertFalse(cache.dpkg_journal_dirty) # that is a dirty journal - open(os.path.join(dpkg_dir,"updates","000"), "w") + open(os.path.join(dpkg_dir,"updates","000"), "w").close() self.assertTrue(cache.dpkg_journal_dirty) # reset config value apt_pkg.config.set("Dir::State::status", old_status) @@ -121,20 +121,19 @@ class TestAptCache(unittest.TestCase): apt_pkg.config.set("dir::etc::sourceparts", "xxx") # main sources.list sources_list = base_sources - f=open(sources_list, "w") - repo = os.path.abspath("./data/test-repo2") - f.write("deb copy:%s /\n" % repo) - f.close() + with open(sources_list, "w") as f: + repo = os.path.abspath("./data/test-repo2") + f.write("deb copy:%s /\n" % repo) # test single sources.list fetching sources_list = os.path.join(rootdir, "test.list") - f=open(sources_list, "w") - repo_dir = os.path.abspath("./data/test-repo") - f.write("deb copy:%s /\n" % repo_dir) - f.close() + with open(sources_list, "w") as f: + repo_dir = os.path.abspath("./data/test-repo") + f.write("deb copy:%s /\n" % repo_dir) + self.assertTrue(os.path.exists(sources_list)) # write marker to ensure listcleaner is not run - open("./data/tmp/var/lib/apt/lists/marker", "w") + open("./data/tmp/var/lib/apt/lists/marker", "w").close() # update a single sources.list cache = apt.Cache() diff --git a/tests/test_hashes.py b/tests/test_hashes.py index e0aabe09..660373cb 100644 --- a/tests/test_hashes.py +++ b/tests/test_hashes.py @@ -82,11 +82,16 @@ class TestHashString(unittest.TestCase): def setUp(self): """Prepare the test by reading the file.""" - self.hashes = apt_pkg.Hashes(open(apt_pkg.__file__)) + self.file = open(apt_pkg.__file__) + self.hashes = apt_pkg.Hashes(self.file) self.md5 = apt_pkg.HashString("MD5Sum", self.hashes.md5) self.sha1 = apt_pkg.HashString("SHA1", self.hashes.sha1) self.sha256 = apt_pkg.HashString("SHA256", self.hashes.sha256) + def tearDown(self): + """Cleanup, Close the file object used for the tests.""" + self.file.close() + def test_md5(self): """hashes: Test apt_pkg.HashString().md5""" self.assertEqual("MD5Sum:%s" % self.hashes.md5, str(self.md5)) diff --git a/tests/test_progress.py b/tests/test_progress.py index ffab5bc0..73853dfa 100644 --- a/tests/test_progress.py +++ b/tests/test_progress.py @@ -34,7 +34,8 @@ class TestProgress(unittest.TestCase): apt_pkg.config.set("Dir::state::lists", "./tmp") # create artifical line deb_line = "deb file:%s/data/fake-packages/ /\n" % basedir - open("fetch_sources.list","w").write(deb_line) + with open("fetch_sources.list","w") as fobj: + fobj.write(deb_line) apt_pkg.config.set("Dir::Etc::sourcelist", "fetch_sources.list") def test_acquire_progress(self): -- cgit v1.2.3 From fedfc6ec4584f43364e13e35326d051f5526700b Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 6 Apr 2011 11:17:40 +0200 Subject: tests/test_apt_cache.py: Use assertTrue() instead of assert_() --- debian/changelog | 1 + tests/test_apt_cache.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/debian/changelog b/debian/changelog index cbe92343..9d708753 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ python-apt (0.8.0~exp2) UNRELEASED; urgency=low * aptsources: Allow insertion of new multi-arch entries * aptsources: Various cleanup work * all: Fix all instances of ResourceWarning about unclosed files + * tests/test_apt_cache.py: Use assertTrue() instead of assert_() -- Julian Andres Klode Wed, 06 Apr 2011 09:46:52 +0200 diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py index 151a20e2..aaa9f601 100644 --- a/tests/test_apt_cache.py +++ b/tests/test_apt_cache.py @@ -48,9 +48,9 @@ class TestAptCache(unittest.TestCase): # tons of seek operations r = pkg.candidate.record self.assertEqual(r['Package'], pkg.shortname) - self.assert_('Version' in r) - self.assert_(len(r['Description']) > 0) - self.assert_(str(r).startswith('Package: %s\n' % pkg.shortname)) + self.assertTrue('Version' in r) + self.assertTrue(len(r['Description']) > 0) + self.assertTrue(str(r).startswith('Package: %s\n' % pkg.shortname)) def test_get_provided_packages(self): cache = apt.Cache() -- 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 'tests') 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 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 'tests') 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 From c8bd732d5cb8be16ae48f8a72a4ed8a266b4ce36 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 29 Jul 2011 19:17:06 +0200 Subject: * tests/test_aptsources_ports.py, tests/test_aptsources.py: - use tmpdir during the tests to fix test failure with apt from experimental --- debian/changelog | 3 +++ tests/test_aptsources.py | 3 ++- tests/test_aptsources_ports.py | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/debian/changelog b/debian/changelog index a25167d5..193f4c58 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,9 @@ python-apt (0.8.1) UNRELEASED; urgency=low the supported methods here * tests/test_debfile.py: - add test for raise on unknown data.tar.xxx + * tests/test_aptsources_ports.py, tests/test_aptsources.py: + - use tmpdir during the tests to fix test failure with apt from + experimental -- Julian Andres Klode Tue, 07 Jun 2011 14:00:22 +0200 diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py index 1597674e..193d3806 100644 --- a/tests/test_aptsources.py +++ b/tests/test_aptsources.py @@ -3,6 +3,7 @@ import unittest import os import copy +import tempfile import apt_pkg import aptsources.sourceslist @@ -17,7 +18,7 @@ class TestAptSources(unittest.TestCase): if apt_pkg.config["APT::Architecture"] not in ('i386', 'amd64'): apt_pkg.config.set("APT::Architecture", "i386") apt_pkg.config.set("Dir::Etc", os.getcwd()) - apt_pkg.config.set("Dir::Etc::sourceparts", "/xxx") + apt_pkg.config.set("Dir::Etc::sourceparts", tempfile.mkdtemp()) if os.path.exists("./build/data/templates"): self.templates = os.path.abspath("./build/data/templates") elif os.path.exists("../build/data/templates"): diff --git a/tests/test_aptsources_ports.py b/tests/test_aptsources_ports.py index 991b532a..67c21b9c 100644 --- a/tests/test_aptsources_ports.py +++ b/tests/test_aptsources_ports.py @@ -1,7 +1,7 @@ #!/usr/bin/env python import os import unittest - +import tempfile import apt_pkg import aptsources.sourceslist @@ -17,7 +17,7 @@ class TestAptSourcesPorts(unittest.TestCase): apt_pkg.config.set("APT::Architecture", "powerpc") apt_pkg.config.set("Dir::Etc", os.path.abspath("data/aptsources_ports")) - apt_pkg.config.set("Dir::Etc::sourceparts", "/xxx") + apt_pkg.config.set("Dir::Etc::sourceparts", tempfile.mkdtemp()) if os.path.exists("../build/data/templates"): self.templates = os.path.abspath("../build/data/templates") else: -- cgit v1.2.3