summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2010-02-13 15:34:24 +0100
committerJulian Andres Klode <jak@debian.org>2010-02-13 15:34:24 +0100
commitc8fa835540d60393f2a1168625bf5d5ae01c4538 (patch)
treeb99415fbe2d2bfe2249c3beb5083c2b0587734c9
parent0401747854d7fc26eb097663822e26a988cf4aa4 (diff)
downloadpython-apt-c8fa835540d60393f2a1168625bf5d5ae01c4538.tar.gz
python/tagfile.cc: Implement the iterator protocol in TagFile.
-rw-r--r--apt/debfile.py3
-rw-r--r--apt/utils.py6
-rw-r--r--debian/changelog2
-rw-r--r--doc/source/library/apt_pkg.rst29
-rw-r--r--python/tag.cc36
5 files changed, 63 insertions, 13 deletions
diff --git a/apt/debfile.py b/apt/debfile.py
index 65f43f20..e27917d5 100644
--- a/apt/debfile.py
+++ b/apt/debfile.py
@@ -448,9 +448,8 @@ class DscSrcPackage(DebPackage):
fobj = open(file)
tagfile = apt_pkg.TagFile(fobj)
- sec = tagfile.section
try:
- while tagfile.step() == 1:
+ for sec in tagfile:
for tag in depends_tags:
if not tag in sec:
continue
diff --git a/apt/utils.py b/apt/utils.py
index 8949c2ab..61d5d54f 100644
--- a/apt/utils.py
+++ b/apt/utils.py
@@ -39,10 +39,10 @@ def get_release_date_from_release_file(path):
if not path or not os.path.exists(path):
return None
tag = apt_pkg.TagFile(open(path))
- tag.step()
- if not "Date" in tag.section:
+ section = tag.next()
+ if not "Date" in section:
return None
- date = tag.section["Date"]
+ date = section["Date"]
return apt_pkg.str_to_time(date)
def get_release_filename_for_pkg(cache, pkgname, label, release):
diff --git a/debian/changelog b/debian/changelog
index b09fb684..fe0d3b9a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -7,6 +7,8 @@ python-apt (0.7.93.2) UNRELEASED; urgency=low
* utils/migrate-0.8.py:
- Improve C++ parsing and add apt.progress.old to the modules, reduces
false positives.
+ * python/tagfile.cc:
+ - Implement the iterator protocol in TagFile.
-- Julian Andres Klode <jak@debian.org> Sun, 07 Feb 2010 19:58:40 +0100
diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst
index 7989a68a..05b3e1fc 100644
--- a/doc/source/library/apt_pkg.rst
+++ b/doc/source/library/apt_pkg.rst
@@ -1407,9 +1407,32 @@ section as a string.
.. class:: TagFile(file)
An object which represents a typical debian control file. Can be used for
- Packages, Sources, control, Release, etc.
+ Packages, Sources, control, Release, etc. Such an object provides two
+ kinds of API which should not be used together:
- An example for working with a TagFile could look like::
+ The first API implements the iterator protocol and should be used whenever
+ possible because it has less side effects than the other one. It may be
+ used e.g. with a for loop::
+
+ tagf = apt_pkg.TagFile(open('/var/lib/dpkg/status'))
+ for section in tagfile:
+ print section['Package']
+
+ .. method:: next()
+
+ A TagFile is its own iterator. This method is part of the iterator
+ protocol and returns a :class:`TagSection` object for the next
+ section in the file. If there is no further section, this method
+ raises the :exc:`StopIteration` exception.
+
+ From Python 3 on, this method is not available anymore, and the
+ global function ``next()`` replaces it.
+
+ The second API uses a shared :class:`TagSection` object which is exposed
+ through the :attr:`section` attribute. This object is modified by calls
+ to :meth:`step` and :meth:`jump`. This API provides more control and may
+ use less memory, but is not recommended because it works by modifying
+ one object. It can be used like this::
tagf = apt_pkg.TagFile(open('/var/lib/dpkg/status'))
tagf.step()
@@ -1418,7 +1441,7 @@ section as a string.
.. method:: step
Step forward to the next section. This simply returns ``1`` if OK, and
- ``0`` if there is no section
+ ``0`` if there is no section.
.. method:: offset
diff --git a/python/tag.cc b/python/tag.cc
index 2aaf3beb..4971a03d 100644
--- a/python/tag.cc
+++ b/python/tag.cc
@@ -258,6 +258,28 @@ static PyObject *TagFileStep(PyObject *Self,PyObject *Args)
return HandleErrors(Py_BuildValue("i",1));
}
+// TagFile Wrappers /*{{{*/
+static PyObject *TagFileNext(PyObject *Self)
+{
+ TagFileData &Obj = *(TagFileData *)Self;
+ // Replace the section.
+ Py_CLEAR(Obj.Section);
+ Obj.Section = (TagSecData*)(&PyTagSection_Type)->tp_alloc(&PyTagSection_Type, 0);
+ new (&Obj.Section->Object) pkgTagSection();
+ Obj.Section->Owner = Self;
+ Py_INCREF(Obj.Section->Owner);
+ Obj.Section->Data = 0;
+ if (Obj.Object.Step(Obj.Section->Object) == false)
+ return HandleErrors(NULL);
+ Py_INCREF(Obj.Section);
+ return HandleErrors(Obj.Section);
+}
+
+static PyObject *TagFileIter(PyObject *Self) {
+ Py_INCREF(Self);
+ return Self;
+}
+
static char *doc_Offset = "Offset() -> Integer";
static PyObject *TagFileOffset(PyObject *Self,PyObject *Args)
{
@@ -541,9 +563,13 @@ static PyGetSetDef TagFileGetSet[] = {
static char *doc_TagFile = "TagFile(file) -> TagFile() object. \n\n"
"TagFile() objects provide access to debian control files, which consists\n"
"of multiple RFC822-like formatted sections.\n\n"
- "A file may consists of multiple sections, and you can use Step() to move\n"
- "forward. The current TagSection() is available via the attribute section"
- ".\n\n"
+ "To provide access to those sections, TagFile objects provide an iterator\n"
+ "which yields TagSection objects for each section.\n\n"
+ "TagFile objects also provide another API which uses a shared TagSection\n"
+ "object in the 'section' member. The functions step() and jump() can be\n"
+ "used to navigate in the file; and offset() tells the current position.\n\n"
+ "It is important to not mix the use of both APIs, because this can have\n"
+ "unwanted effects.\n\n"
"The parameter *file* refers to an object providing a fileno() method or\n"
"a file descriptor (an integer)";
@@ -578,8 +604,8 @@ PyTypeObject PyTagFile_Type =
TagFileClear, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
- 0, // tp_iter
- 0, // tp_iternext
+ TagFileIter, // tp_iter
+ TagFileNext, // tp_iternext
TagFileMethods, // tp_methods
0, // tp_members
TagFileGetSet, // tp_getset