From 6c3e74bdf3a8bd6aced0a2ddb38c1cc7b22ec655 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 13 Apr 2009 18:19:41 +0200 Subject: * doc/source/conf.py: Do not require python-debian anymore Try to get the release from the information in the environment variable DEBVER, which is exported in debian/rules. If it is not set, use python-debian to read the release from the changelog. --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 4c7b542f..72476c58 100644 --- a/debian/control +++ b/debian/control @@ -12,7 +12,6 @@ Build-Depends: apt-utils, python-all-dbg, python-all-dev, python-central (>= 0.5), - python-debian, python-distutils-extra (>= 1.9.0), python-gtk2, python-sphinx (>= 0.5), -- cgit v1.2.3 From 506cb021d62e643fba38ddb4b84572a86cb3a3ba Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 13 Apr 2009 18:27:43 +0200 Subject: * python/tag.cc: Support 'key in mapping' for TagSections Support the replacement of mapping.has_key() for sections, and update the usage in apt/package.py and apt/debfile accordingly. This is implemented by extending the TagSecType with sequence methods, but only settings the contains method there. The TagSecGetAttr() function has been removed and replaced by the use of the tp_methods slot. --- apt/debfile.py | 10 +++++----- apt/package.py | 4 ++-- debian/changelog | 7 +++++++ doc/source/apt_pkg/cache.rst | 4 ++++ python/apt_pkgmodule.cc | 4 ++++ python/tag.cc | 47 +++++++++++++++++++++++++++++--------------- 6 files changed, 53 insertions(+), 23 deletions(-) (limited to 'debian') diff --git a/apt/debfile.py b/apt/debfile.py index 0406a250..8d4f534c 100644 --- a/apt/debfile.py +++ b/apt/debfile.py @@ -463,18 +463,18 @@ class DscSrcPackage(DebPackage): try: while tagfile.Step() == 1: for tag in depends_tags: - if not sec.has_key(tag): + if not tag in sec: continue self._depends.extend(apt_pkg.ParseSrcDepends(sec[tag])) for tag in conflicts_tags: - if not sec.has_key(tag): + if not tag in sec: continue self._conflicts.extend(apt_pkg.ParseSrcDepends(sec[tag])) - if sec.has_key('Source'): + if 'Source' in sec: self.pkgname = sec['Source'] - if sec.has_key('Binary'): + if 'Binary' in sec: self.binaries = sec['Binary'].split(', ') - if sec.has_key('Version'): + if 'Version' in sec: self._sections['Version'] = sec['Version'] finally: del sec diff --git a/apt/package.py b/apt/package.py index ec88a456..e308da4b 100644 --- a/apt/package.py +++ b/apt/package.py @@ -157,7 +157,7 @@ class Record(object): return self._rec[key] def __contains__(self, key): - return self._rec.has_key(key) + return key in self._rec def __iter__(self): return iter(self._rec.keys()) @@ -176,7 +176,7 @@ class Record(object): def has_key(self, key): """deprecated form of 'key in x'.""" - return self._rec.has_key(key) + return key in self._rec class Version(object): diff --git a/debian/changelog b/debian/changelog index 83b00150..f623254e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +python-apt (0.7.11) UNRELEASED; urgency=low + + * python/tag.cc: + - Support 'key in mapping' for TagSections + + -- Julian Andres Klode Mon, 13 Apr 2009 18:08:10 +0200 + python-apt (0.7.10.3) unstable; urgency=low * apt/package.py: Handle cases where no candidate is available, by returning diff --git a/doc/source/apt_pkg/cache.rst b/doc/source/apt_pkg/cache.rst index af67d82f..146c2c2a 100644 --- a/doc/source/apt_pkg/cache.rst +++ b/doc/source/apt_pkg/cache.rst @@ -1199,6 +1199,10 @@ broken dependencies: Return the value of the field at *key*. If *key* is not available, raise :exc:`KeyError`. + .. describe:: key in section + + Return ``True`` if *section* has a key *key*, else ``False``. + .. method:: Bytes The number of bytes in the section. diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 86732781..34669fd5 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -472,6 +472,10 @@ static void AddInt(PyObject *Dict,const char *Itm,unsigned long I) extern "C" void initapt_pkg() { + // Finalize our types to add slots, etc. + if (PyType_Ready(&TagSecType) == -1) return; + + // Initialize the module PyObject *Module = Py_InitModule("apt_pkg",methods); PyObject *Dict = PyModule_GetDict(Module); diff --git a/python/tag.cc b/python/tag.cc index 217be290..cab32370 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -174,6 +174,16 @@ static PyObject *TagSecExists(PyObject *Self,PyObject *Args) return Py_BuildValue("i",1); } +static int TagSecContains(PyObject *Self,PyObject *Arg) +{ + char *Name = PyString_AsString(Arg); + const char *Start; + const char *Stop; + if (GetCpp(Self).Find(Name,Start,Stop) == false) + return 0; + return 1; +} + static char *doc_Bytes = "Bytes() -> integer"; static PyObject *TagSecBytes(PyObject *Self,PyObject *Args) { @@ -365,36 +375,41 @@ static PyMethodDef TagSecMethods[] = {} }; -// TagSecGetAttr - Get an attribute - variable/method /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static PyObject *TagSecGetAttr(PyObject *Self,char *Name) -{ - return Py_FindMethod(TagSecMethods,Self,Name); -} - /*}}}*/ -// Type for a Tag Section + +PySequenceMethods TagSecSeqMeth = {0,0,0,0,0,0,0,TagSecContains,0,0}; PyMappingMethods TagSecMapMeth = {TagSecLength,TagSecMap,0}; PyTypeObject TagSecType = { PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "TagSection", // tp_name + 0, // ob_size + "TagSection", // tp_name sizeof(TagSecData), // tp_basicsize 0, // tp_itemsize // Methods TagSecFree, // tp_dealloc - 0, // tp_print - TagSecGetAttr, // tp_getattr + 0, // tp_print + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number - 0, // tp_as_sequence + &TagSecSeqMeth, // tp_as_sequence &TagSecMapMeth, // tp_as_mapping 0, // tp_hash - 0, // tp_call - TagSecStr, // tp_str + 0, // tp_call + TagSecStr, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "TagSection Object", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + TagSecMethods // tp_methods }; // Method table for the Tag File object -- cgit v1.2.3 From 62d7f4b80d56ef1e27039441cd6584cfb71d6502 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 13 Apr 2009 19:13:25 +0200 Subject: * python/*.cc: Use PyObject_AsFileDescriptor instead of fileno(PyFile_AsFile) Replace support for file objects with a more generic support for any object providing a fileno() method and for file descriptors (integers). This also helps us to port to Python 3, where the previously used PyFile_ functions are not available anymore. --- debian/changelog | 2 ++ python/apt_instmodule.cc | 21 +++++++++++++++------ python/apt_pkgmodule.cc | 12 ++++++------ python/tag.cc | 7 +++++-- python/tar.cc | 17 +++++++++++------ 5 files changed, 39 insertions(+), 20 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index f623254e..dc8d1545 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,8 @@ python-apt (0.7.11) UNRELEASED; urgency=low * python/tag.cc: - Support 'key in mapping' for TagSections + * Replace support for file objects with a more generic support for any object + providing a fileno() method and for file descriptors (integers). -- Julian Andres Klode Mon, 13 Apr 2009 18:08:10 +0200 diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index 48868d86..a9d81be4 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -35,14 +35,17 @@ static PyObject *debExtractControl(PyObject *Self,PyObject *Args) { char *Member = "control"; PyObject *File; - if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Member) == 0) + if (PyArg_ParseTuple(Args,"O|s",&File,&Member) == 0) return 0; // Subscope makes sure any clean up errors are properly handled. PyObject *Res = 0; { // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + FileFd Fd(fileno,false); debDebFile Deb(Fd); if (_error->PendingError() == true) return HandleErrors(); @@ -76,7 +79,7 @@ static PyObject *debExtractArchive(PyObject *Self,PyObject *Args) char *Rootdir = NULL; char cwd[512]; PyObject *File; - if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Rootdir) == 0) + if (PyArg_ParseTuple(Args,"O|s",&File,&Rootdir) == 0) return 0; // Subscope makes sure any clean up errors are properly handled. @@ -89,7 +92,10 @@ static PyObject *debExtractArchive(PyObject *Self,PyObject *Args) } // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + FileFd Fd(fileno,false); debDebFile Deb(Fd); if (_error->PendingError() == true) { if (Rootdir != NULL) @@ -118,11 +124,14 @@ static PyObject *arCheckMember(PyObject *Self,PyObject *Args) char *Member = NULL; bool res = false; PyObject *File; - if (PyArg_ParseTuple(Args,"O!s",&PyFile_Type,&File,&Member) == 0) + if (PyArg_ParseTuple(Args,"Os",&File,&Member) == 0) return 0; // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + FileFd Fd(fileno,false); ARArchive AR(Fd); if (_error->PendingError() == true) return HandleErrors(Py_BuildValue("b",res)); diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 1417e5d0..10d98911 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -184,10 +184,10 @@ static PyObject *md5sum(PyObject *Self,PyObject *Args) } // Digest of a file - if (PyFile_Check(Obj) != 0) + int Fd = PyObject_AsFileDescriptor(Obj); + if (Fd != -1) { MD5Summation Sum; - int Fd = fileno(PyFile_AsFile(Obj)); struct stat St; if (fstat(Fd,&St) != 0 || Sum.AddFD(Fd,St.st_size) == false) @@ -224,10 +224,10 @@ static PyObject *sha1sum(PyObject *Self,PyObject *Args) } // Digest of a file - if (PyFile_Check(Obj) != 0) + int Fd = PyObject_AsFileDescriptor(Obj); + if (Fd != -1) { SHA1Summation Sum; - int Fd = fileno(PyFile_AsFile(Obj)); struct stat St; if (fstat(Fd,&St) != 0 || Sum.AddFD(Fd,St.st_size) == false) @@ -264,10 +264,10 @@ static PyObject *sha256sum(PyObject *Self,PyObject *Args) } // Digest of a file - if (PyFile_Check(Obj) != 0) + int Fd = PyObject_AsFileDescriptor(Obj); + if (Fd != -1) { SHA256Summation Sum; - int Fd = fileno(PyFile_AsFile(Obj)); struct stat St; if (fstat(Fd,&St) != 0 || Sum.AddFD(Fd,St.st_size) == false) diff --git a/python/tag.cc b/python/tag.cc index f3fb2e6c..baf97b59 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -272,11 +272,14 @@ char *doc_ParseTagFile = "ParseTagFile(File) -> TagFile"; PyObject *ParseTagFile(PyObject *self,PyObject *Args) { PyObject *File; - if (PyArg_ParseTuple(Args,"O!",&PyFile_Type,&File) == 0) + if (PyArg_ParseTuple(Args,"O",&File) == 0) + return 0; + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) return 0; TagFileData *New = PyObject_NEW(TagFileData,&TagFileType); - new (&New->Fd) FileFd(fileno(PyFile_AsFile(File)),false); + new (&New->Fd) FileFd(fileno,false); New->File = File; Py_INCREF(New->File); new (&New->Object) pkgTagFile(&New->Fd); diff --git a/python/tar.cc b/python/tar.cc index e5aaee6f..f0d57823 100644 --- a/python/tar.cc +++ b/python/tar.cc @@ -97,8 +97,7 @@ PyObject *tarExtract(PyObject *Self,PyObject *Args) PyObject *Function; char *Comp; - if (PyArg_ParseTuple(Args,"O!Os",&PyFile_Type,&File, - &Function,&Comp) == 0) + if (PyArg_ParseTuple(Args,"OOs",&File, &Function,&Comp) == 0) return 0; if (PyCallable_Check(Function) == 0) @@ -109,7 +108,11 @@ PyObject *tarExtract(PyObject *Self,PyObject *Args) { // Open the file and associate the tar - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + + FileFd Fd(fileno,false); ExtractTar Tar(Fd,0xFFFFFFFF,Comp); if (_error->PendingError() == true) return HandleErrors(); @@ -139,8 +142,7 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) char *Chunk; const char *Comp = "gzip"; - if (PyArg_ParseTuple(Args,"O!Os",&PyFile_Type,&File, - &Function,&Chunk) == 0) + if (PyArg_ParseTuple(Args,"OOs",&File,&Function,&Chunk) == 0) return 0; if (PyCallable_Check(Function) == 0) @@ -149,10 +151,13 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) return 0; } + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; { // Open the file and associate the tar // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + FileFd Fd(fileno,false); debDebFile Deb(Fd); if (_error->PendingError() == true) return HandleErrors(); -- cgit v1.2.3 From ebedf54fd4c72bfbf5c5e60d3d908cd66acace95 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 13 Apr 2009 19:28:33 +0200 Subject: * python/cache.cc: Add support for the Breaks fields This also fixes problems on packages with Breaks field, where the lookup of the field name leads to some unprintable characters (because the index exceeds the number of items). --- debian/changelog | 1 + python/cache.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index dc8d1545..29927989 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ python-apt (0.7.11) UNRELEASED; urgency=low - Support 'key in mapping' for TagSections * Replace support for file objects with a more generic support for any object providing a fileno() method and for file descriptors (integers). + * Add support for the Breaks fields -- Julian Andres Klode Mon, 13 Apr 2009 18:08:10 +0200 diff --git a/python/cache.cc b/python/cache.cc index 0c59f561..4db097c7 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -502,7 +502,7 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, { "", "Depends","PreDepends","Suggests", "Recommends","Conflicts","Replaces", - "Obsoletes" + "Obsoletes", "Breaks" }; PyObject *Dep = PyString_FromString(Types[Start->Type]); LastDepType = Start->Type; -- cgit v1.2.3 From ccd98916ba50c7583f354e0d3487ffb0830103f0 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 13 Apr 2009 20:00:09 +0200 Subject: * python/configuration.cc: Support the 'in' operator for Configuration Support the replacement of mapping.has_key() for Configuration,ConfigurationPtr and ConfigurationSub objects. This is implemented by extending the various types with the tp_as_sequence slot, which refers to a PySequenceMethods containing only this method. The CnfGetAttr() function has been removed and replaced by the use of the tp_method slot. This helps the py3k port because the previously used Py_FindMethod() is not avilable anymore. This completes the support of the 'in' operator in all python-apt objects, which makes it even easier to convert python-apt-using applications to py3k once python-apt supports it, as 2to3 converts 'm.has_key(k)' to 'k in m'. Also finalize the types in apt_pkgmodule.cc and add the new 'key in conf' description to the documentation. --- debian/changelog | 4 +-- doc/source/apt_pkg/cache.rst | 4 +++ python/apt_pkgmodule.cc | 3 ++ python/configuration.cc | 70 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 64 insertions(+), 17 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 29927989..261ff7bd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,7 @@ python-apt (0.7.11) UNRELEASED; urgency=low - * python/tag.cc: - - Support 'key in mapping' for TagSections + * Support the 'in' operator (e.g. "k in d") in Configuration{,Ptr,Sub} + objects (e.g. apt_pkg.Config) and in TagSections (apt_pkg.ParseSection()) * Replace support for file objects with a more generic support for any object providing a fileno() method and for file descriptors (integers). * Add support for the Breaks fields diff --git a/doc/source/apt_pkg/cache.rst b/doc/source/apt_pkg/cache.rst index 146c2c2a..3ecbf069 100644 --- a/doc/source/apt_pkg/cache.rst +++ b/doc/source/apt_pkg/cache.rst @@ -117,6 +117,10 @@ Classes in apt_pkg The Configuration objects store the configuration of apt. + .. describe:: key in conf + + Return ``True`` if *conf* has a key *key*, else ``False``. + .. describe:: conf[key] Return the value of the option given key *key*. If it does not diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 10d98911..3d043179 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -475,6 +475,9 @@ extern "C" void initapt_pkg() // Finalize our types to add slots, etc. if (PyType_Ready(&TagSecType) == -1) return; if (PyType_Ready(&TagFileType) == -1) return; + if (PyType_Ready(&ConfigurationType) == -1) return; + if (PyType_Ready(&ConfigurationPtrType) == -1) return; + if (PyType_Ready(&ConfigurationSubType) == -1) return; // Initialize the module PyObject *Module = Py_InitModule("apt_pkg",methods); diff --git a/python/configuration.cc b/python/configuration.cc index 21f70bc1..a95ac029 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -128,6 +128,11 @@ static PyObject *CnfExists(PyObject *Self,PyObject *Args) return Py_BuildValue("i",(int)GetSelf(Self).Exists(Name)); } +static int CnfContains(PyObject *Self,PyObject *Arg) +{ + return (int)GetSelf(Self).Exists(PyString_AsString(Arg)); +} + static char *doc_Clear = "Clear(Name) -> None"; static PyObject *CnfClear(PyObject *Self,PyObject *Args) { @@ -470,34 +475,41 @@ static PyMethodDef CnfMethods[] = {} }; -// CnfGetAttr - Get an attribute - variable/method /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static PyObject *CnfGetAttr(PyObject *Self,char *Name) -{ - return Py_FindMethod(CnfMethods,Self,Name); -} - // Type for a Normal Configuration object +static PySequenceMethods ConfigurationSeq = {0,0,0,0,0,0,0,CnfContains,0,0}; static PyMappingMethods ConfigurationMap = {0,CnfMap,CnfMapSet}; PyTypeObject ConfigurationType = { PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size + 0, // ob_size "Configuration", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods CppDealloc, // tp_dealloc 0, // tp_print - CnfGetAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number - 0, // tp_as_sequence + &ConfigurationSeq, // tp_as_sequence &ConfigurationMap, // 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 + "Configuration Object", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + CnfMethods, // tp_methods }; PyTypeObject ConfigurationPtrType = @@ -510,14 +522,28 @@ PyTypeObject ConfigurationPtrType = // Methods (destructor)PyObject_Free, // tp_dealloc 0, // tp_print - CnfGetAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number - 0, // tp_as_sequence + &ConfigurationSeq, // tp_as_sequence &ConfigurationMap, // 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 + "ConfigurationPtr Object", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + CnfMethods, // tp_methods }; PyTypeObject ConfigurationSubType = @@ -530,13 +556,27 @@ PyTypeObject ConfigurationSubType = // Methods CnfSubFree, // tp_dealloc 0, // tp_print - CnfGetAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number - 0, // tp_as_sequence + &ConfigurationSeq, // tp_as_sequence &ConfigurationMap, // 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 + "ConfigurationSub Object", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + CnfMethods, // tp_methods }; -- cgit v1.2.3 From 2b867aebe32d59b7450f3a7fb22390e0dd9f8cc7 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Apr 2009 14:16:28 +0200 Subject: * apt/cache.py: Use set() and WeakValueDictionary() for holding packages. Only create Package objects when they are requested, do not keep them in a dict. Saves 10MB for 25,000 packages on my machine. The set holds the names of all packages which have at least one version, and the WeakValueDictionary() holds weak references to created Package objects. This way accessing the same package two times should return the same object, kept by the WeakValueDictionary(). --- apt/cache.py | 38 +++++++++++++++++++++++--------------- debian/changelog | 4 +++- 2 files changed, 26 insertions(+), 16 deletions(-) (limited to 'debian') diff --git a/apt/cache.py b/apt/cache.py index cc425ccb..d13010af 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -20,6 +20,7 @@ # USA import os +import weakref import apt_pkg from apt import Package @@ -80,7 +81,8 @@ class Cache(object): self._records = apt_pkg.GetPkgRecords(self._cache) self._list = apt_pkg.GetPkgSourceList() self._list.ReadMainList() - self._dict = {} + self._set = set() + self._weakref = weakref.WeakValueDictionary() progress.Op = "Building data structures" i=last=0 @@ -91,7 +93,7 @@ class Cache(object): last=i # drop stuff with no versions (cruft) if len(pkg.VersionList) > 0: - self._dict[pkg.Name] = Package(self, pkg) + self._set.add(pkg.Name) i += 1 @@ -100,30 +102,36 @@ class Cache(object): def __getitem__(self, key): """ look like a dictionary (get key) """ - return self._dict[key] + try: + return self._weakref[key] + except KeyError: + if key in self._set: + pkg = self._weakref[key] = Package(self, self._cache[key]) + return pkg + else: + raise KeyError('The cache has no package named %r' % key) def __iter__(self): - for pkgname in self._dict.keys(): - yield self._dict[pkgname] + for pkgname in self._set: + yield self[pkgname] raise StopIteration def has_key(self, key): - return (key in self._dict) + return (key in self._set) def __contains__(self, key): - return (key in self._dict) + return (key in self._set) def __len__(self): - return len(self._dict) + return len(self._set) def keys(self): - return self._dict.keys() + return list(self._set) def getChanges(self): """ Get the marked changes """ changes = [] - for name in self._dict.keys(): - p = self._dict[name] + for p in self: if p.markedUpgrade or p.markedInstall or p.markedDelete or \ p.markedDowngrade or p.markedReinstall: changes.append(p) @@ -348,7 +356,7 @@ class FilteredCache(object): return len(self._filtered) def __getitem__(self, key): - return self.cache._dict[key] + return self.cache[key] def __iter__(self): for pkgname in self._filtered: @@ -366,10 +374,10 @@ class FilteredCache(object): def _reapplyFilter(self): " internal helper to refilter " self._filtered = {} - for pkg in self.cache._dict.keys(): + for pkg in self.cache: for f in self._filters: - if f.apply(self.cache._dict[pkg]): - self._filtered[pkg] = 1 + if f.apply(pkg): + self._filtered[pkg.name] = 1 break def setFilter(self, filter): diff --git a/debian/changelog b/debian/changelog index 261ff7bd..6cbdaac7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,8 +5,10 @@ python-apt (0.7.11) UNRELEASED; urgency=low * Replace support for file objects with a more generic support for any object providing a fileno() method and for file descriptors (integers). * Add support for the Breaks fields + * Only create Package objects when they are requested, do not keep them in + a dict. Saves 10MB for 25,000 packages on my machine. - -- Julian Andres Klode Mon, 13 Apr 2009 18:08:10 +0200 + -- Julian Andres Klode Wed, 15 Apr 2009 13:47:42 +0200 python-apt (0.7.10.3) unstable; urgency=low -- cgit v1.2.3 From c876c5095673a2f1c0f2c0eef6eadef2ce200e19 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Apr 2009 16:19:12 +0200 Subject: * Introduce support for Python 3 (Closes: #523645) This is the first initial port to Python 3. The API is almost completely identical to the one found in Python 2, except that functions working with binary data require bytes (md5sum,sha1sum,sha256sum,Base64Encode). Using setup3.py to install the modules will not work, because the apt package still has to be converted to Python 3. For the package, we call 2to3-3.1 in debian/rules to do this automatically. --- apt/package.py | 6 +++- debian/changelog | 2 ++ debian/control | 2 ++ debian/rules | 26 +++++++++++++-- po/python-apt.pot | 10 +++--- python/acquire.cc | 6 ++++ python/apt_instmodule.cc | 35 ++++++++++++++++++- python/apt_pkgmodule.cc | 87 +++++++++++++++++++++++++++++++++++------------- python/cache.cc | 18 ++++++++++ python/cdrom.cc | 2 ++ python/configuration.cc | 6 ++++ python/depcache.cc | 6 ++++ python/generic.h | 25 ++++++++++++++ python/indexfile.cc | 2 ++ python/metaindex.cc | 2 ++ python/pkgmanager.cc | 2 ++ python/pkgrecords.cc | 2 ++ python/pkgsrcrecords.cc | 2 ++ python/sourcelist.cc | 2 ++ python/string.cc | 16 ++++++++- python/tag.cc | 4 +++ setup3.py | 77 ++++++++++++++++++++++++++++++++++++++++++ 22 files changed, 307 insertions(+), 33 deletions(-) create mode 100644 setup3.py (limited to 'debian') diff --git a/apt/package.py b/apt/package.py index 3ea1105d..f12f5559 100644 --- a/apt/package.py +++ b/apt/package.py @@ -272,8 +272,12 @@ class Version(object): """ self.summary # This does the lookup for us. desc = '' + + dsc = self.package._pcache._records.LongDesc try: - dsc = unicode(self.package._pcache._records.LongDesc, "utf-8") + if not isinstance(dsc, unicode): + # Only convert where needed (i.e. Python 2.X) + dsc = unicode(dsc, "utf-8") except UnicodeDecodeError, err: return _("Invalid unicode in description for '%s' (%s). " "Please report.") % (self.package.name, err) diff --git a/debian/changelog b/debian/changelog index 6cbdaac7..a9518d7d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,7 @@ python-apt (0.7.11) UNRELEASED; urgency=low + * Introduce support for Python 3 (Closes: #523645) + * Support the 'in' operator (e.g. "k in d") in Configuration{,Ptr,Sub} objects (e.g. apt_pkg.Config) and in TagSections (apt_pkg.ParseSection()) * Replace support for file objects with a more generic support for any object diff --git a/debian/control b/debian/control index 72476c58..08ee329f 100644 --- a/debian/control +++ b/debian/control @@ -11,6 +11,8 @@ Build-Depends: apt-utils, libapt-pkg-dev (>= 0.7.10), python-all-dbg, python-all-dev, + python3.1-dev, + python3.1-dbg, python-central (>= 0.5), python-distutils-extra (>= 1.9.0), python-gtk2, diff --git a/debian/rules b/debian/rules index 6d709ecd..7de945f2 100755 --- a/debian/rules +++ b/debian/rules @@ -11,22 +11,44 @@ DEB_PYTHON_PACKAGES_EXCLUDE=python-apt-dbg include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/python-distutils.mk +PY3K = y PKG=python-apt DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS) export DEBVER + +ifeq ($(PY3K),y) +build/python-apt:: + python3.1 setup3.py build + +install/python-apt:: + python3.1 ./setup3.py install --root $(CURDIR)/debian/python-apt \ + --install-layout=deb --no-compile + + find $(CURDIR)/debian/python-apt/usr/lib/python3.1/dist-packages/ -name '*.py' \ + | xargs 2to3-3.1 | patch -p0 +endif + build/python-apt-dbg:: set -e; \ for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py build; \ done + ifeq($(PY3K),y) + python3.1-dbg ./setup3.py build + endif install/python-apt-dbg:: for i in $(cdbs_python_build_versions); do \ - python$$i-dbg ./setup.py install --root $(CURDIR)/debian/python-apt-dbg; \ + python$$i-dbg ./setup.py install --root $(CURDIR)/debian/python-apt-dbg \ + --no-compile; \ done + ifeq($(PY3K),y) + python3.1-dbg ./setup3.py install --root $(CURDIR)/debian/python-apt-dbg \ + --install-layout=deb --no-compile + endif find debian/python-apt-dbg \ ! -type d ! -name '*_d.so' | xargs rm -f find debian/python-apt-dbg -depth -empty -exec rmdir {} \; @@ -39,4 +61,4 @@ binary-predeb/python-apt-dbg:: ln -s python-apt debian/python-apt-dbg/usr/share/doc/python-apt-dbg clean:: - rm -rf build/lib* build/temp* + rm -rf build/lib* build/temp* build diff --git a/po/python-apt.pot b/po/python-apt.pot index 9c23c579..d12ae967 100644 --- a/po/python-apt.pot +++ b/po/python-apt.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-04-12 19:07+0200\n" +"POT-Creation-Date: 2009-04-15 16:10+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -354,16 +354,16 @@ msgstr "" msgid "Complete" msgstr "" -#: ../apt/package.py:278 +#: ../apt/package.py:282 #, python-format msgid "Invalid unicode in description for '%s' (%s). Please report." msgstr "" -#: ../apt/package.py:745 ../apt/package.py:849 +#: ../apt/package.py:830 ../apt/package.py:934 msgid "The list of changes is not available" msgstr "" -#: ../apt/package.py:853 +#: ../apt/package.py:938 #, python-format msgid "" "The list of changes is not available yet.\n" @@ -372,7 +372,7 @@ msgid "" "until the changes become available or try again later." msgstr "" -#: ../apt/package.py:859 +#: ../apt/package.py:944 msgid "" "Failed to download the list of changes. \n" "Please check your Internet connection." diff --git a/python/acquire.cc b/python/acquire.cc index d39ee495..053753cd 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -72,7 +72,9 @@ static PyObject *AcquireItemRepr(PyObject *Self) PyTypeObject AcquireItemType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgAcquire::ItemIterator", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -175,7 +177,9 @@ static PyGetSetDef PkgAcquireGetSet[] = { PyTypeObject PkgAcquireType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "Acquire", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize @@ -234,7 +238,9 @@ PyObject *GetAcquire(PyObject *Self,PyObject *Args) PyTypeObject PkgAcquireFileType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgAcquireFile", // tp_name sizeof(CppPyObject),// tp_basicsize 0, // tp_itemsize diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index a9d81be4..09e3937e 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -162,8 +162,41 @@ static PyMethodDef methods[] = {} }; +#if PY_MAJOR_VERSION >= 3 +struct module_state { + PyObject *error; +}; +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) + +static int apt_inst_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +static int apt_inst_clear(PyObject *m) { + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "apt_inst", + NULL, + sizeof(struct module_state), + methods, + NULL, + apt_inst_traverse, + apt_inst_clear, + NULL +}; + +extern "C" PyObject * PyInit_apt_inst() +{ + return PyModule_Create(&moduledef); +} +#else extern "C" void initapt_inst() { Py_InitModule("apt_inst",methods); } - /*}}}*/ +#endif /*}}}*/ diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index fe6a739e..e71d8ee6 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -173,12 +173,12 @@ static PyObject *md5sum(PyObject *Self,PyObject *Args) return 0; // Digest of a string. - if (PyString_Check(Obj) != 0) + if (PyBytes_Check(Obj) != 0) { char *s; Py_ssize_t len; MD5Summation Sum; - PyString_AsStringAndSize(Obj, &s, &len); + PyBytes_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); } @@ -213,12 +213,12 @@ static PyObject *sha1sum(PyObject *Self,PyObject *Args) return 0; // Digest of a string. - if (PyString_Check(Obj) != 0) + if (PyBytes_Check(Obj) != 0) { char *s; Py_ssize_t len; SHA1Summation Sum; - PyString_AsStringAndSize(Obj, &s, &len); + PyBytes_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); } @@ -253,12 +253,12 @@ static PyObject *sha256sum(PyObject *Self,PyObject *Args) return 0; // Digest of a string. - if (PyString_Check(Obj) != 0) + if (PyBytes_Check(Obj) != 0) { char *s; Py_ssize_t len; SHA256Summation Sum; - PyString_AsStringAndSize(Obj, &s, &len); + PyBytes_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); } @@ -470,30 +470,68 @@ static void AddInt(PyObject *Dict,const char *Itm,unsigned long I) Py_DECREF(Obj); } +#if PY_MAJOR_VERSION >= 3 +struct module_state { + PyObject *error; +}; + +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) + +static int apt_inst_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +static int apt_inst_clear(PyObject *m) { + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "apt_inst", + NULL, + sizeof(struct module_state), + methods, + NULL, + apt_inst_traverse, + apt_inst_clear, + NULL +}; + +#define INIT_ERROR return 0 +extern "C" PyObject * PyInit_apt_pkg() +#else +#define INIT_ERROR return extern "C" void initapt_pkg() +#endif { // Finalize our types to add slots, etc. - if (PyType_Ready(&TagSecType) == -1) return; - if (PyType_Ready(&TagFileType) == -1) return; - if (PyType_Ready(&ConfigurationType) == -1) return; - if (PyType_Ready(&ConfigurationPtrType) == -1) return; - if (PyType_Ready(&ConfigurationSubType) == -1) return; - if (PyType_Ready(&PkgCdromType) == -1) return; - if (PyType_Ready(&PkgProblemResolverType) == -1) return; - if (PyType_Ready(&PkgActionGroupType) == -1) return; - if (PyType_Ready(&PkgSourceListType) == -1) return; - if (PyType_Ready(&PkgCacheType) == -1) return; - if (PyType_Ready(&DependencyType) == -1) return; - if (PyType_Ready(&PkgDepCacheType) == -1) return; - if (PyType_Ready(&PkgAcquireType) == -1) return; - if (PyType_Ready(&PackageIndexFileType) == -1) return; - if (PyType_Ready(&PkgManagerType) == -1) return; - if (PyType_Ready(&PkgSrcRecordsType) == -1) return; - if (PyType_Ready(&PkgRecordsType) == -1) return; + if (PyType_Ready(&TagSecType) == -1) INIT_ERROR; + if (PyType_Ready(&TagFileType) == -1) INIT_ERROR; + if (PyType_Ready(&ConfigurationType) == -1) INIT_ERROR; + if (PyType_Ready(&ConfigurationPtrType) == -1) INIT_ERROR; + if (PyType_Ready(&ConfigurationSubType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgCdromType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgProblemResolverType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgActionGroupType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgSourceListType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgCacheType) == -1) INIT_ERROR; + if (PyType_Ready(&DependencyType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgDepCacheType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgAcquireType) == -1) INIT_ERROR; + if (PyType_Ready(&PackageIndexFileType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgManagerType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgSrcRecordsType) == -1) INIT_ERROR; + if (PyType_Ready(&PkgRecordsType) == -1) INIT_ERROR; // Initialize the module + #if PY_MAJOR_VERSION >= 3 + PyObject *Module = PyModule_Create(&moduledef); + #else PyObject *Module = Py_InitModule("apt_pkg",methods); + #endif PyObject *Dict = PyModule_GetDict(Module); // Global variable linked to the global configuration class @@ -549,6 +587,9 @@ extern "C" void initapt_pkg() AddInt(Dict,"InstStateReInstReq",pkgCache::State::ReInstReq); AddInt(Dict,"InstStateHold",pkgCache::State::Hold); AddInt(Dict,"InstStateHoldReInstReq",pkgCache::State::HoldReInstReq); + #if PY_MAJOR_VERSION >= 3 + return Module; + #endif } /*}}}*/ diff --git a/python/cache.cc b/python/cache.cc index 2d8b8db7..957681ba 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -239,7 +239,9 @@ static PyMappingMethods CacheMap = {0,CacheMapOp,0}; PyTypeObject PkgCacheType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -277,7 +279,9 @@ PyTypeObject PkgCacheType = PyTypeObject PkgCacheFileType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCacheFile", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -345,7 +349,9 @@ static PySequenceMethods PkgListSeq = PyTypeObject PkgListType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache::PkgIterator", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -435,7 +441,9 @@ static PyObject *PackageRepr(PyObject *Self) PyTypeObject PackageType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache::Package", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -498,7 +506,9 @@ static PyObject *DescriptionRepr(PyObject *Self) PyTypeObject DescriptionType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache::DescIterator", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -684,7 +694,9 @@ static PyObject *VersionRepr(PyObject *Self) PyTypeObject VersionType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache::VerIterator", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -759,7 +771,9 @@ static PyObject *PackageFileRepr(PyObject *Self) PyTypeObject PackageFileType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache::PkgFileIterator", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -905,7 +919,9 @@ static PyGetSetDef DependencyGetSet[] = { PyTypeObject DependencyType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache::DepIterator", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -991,7 +1007,9 @@ static PySequenceMethods RDepListSeq = PyTypeObject RDepListType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgCache::DepIterator", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/cdrom.cc b/python/cdrom.cc index 0816d93e..b3a38438 100644 --- a/python/cdrom.cc +++ b/python/cdrom.cc @@ -67,7 +67,9 @@ static PyMethodDef PkgCdromMethods[] = PyTypeObject PkgCdromType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "Cdrom", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/configuration.cc b/python/configuration.cc index b4adf357..eaac48ec 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -481,7 +481,9 @@ static PyMappingMethods ConfigurationMap = {0,CnfMap,CnfMapSet}; PyTypeObject ConfigurationType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "Configuration", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize @@ -515,7 +517,9 @@ PyTypeObject ConfigurationType = PyTypeObject ConfigurationPtrType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "ConfigurationPtr", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize @@ -549,7 +553,9 @@ PyTypeObject ConfigurationPtrType = PyTypeObject ConfigurationSubType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "ConfigurationSub", // tp_name sizeof(SubConfiguration), // tp_basicsize 0, // tp_itemsize diff --git a/python/depcache.cc b/python/depcache.cc index ade3d4f5..1c9eeff7 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -594,7 +594,9 @@ static PyGetSetDef PkgDepCacheGetSet[] = { PyTypeObject PkgDepCacheType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgDepCache", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -773,7 +775,9 @@ static PyMethodDef PkgProblemResolverMethods[] = PyTypeObject PkgProblemResolverType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgProblemResolver", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -829,7 +833,9 @@ static PyMethodDef PkgActionGroupMethods[] = PyTypeObject PkgActionGroupType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgActionGroup", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/generic.h b/python/generic.h index ce79a54c..6e66d24c 100644 --- a/python/generic.h +++ b/python/generic.h @@ -35,6 +35,31 @@ typedef int Py_ssize_t; #endif +/* Define compatibility for Python 3. + * + * We will use the names PyString_* to refer to the default string type + * of the current Python version (PyString on 2.X, PyUnicode on 3.X). + * + * When we really need unicode strings, we will use PyUnicode_* directly, as + * long as it exists in Python 2 and Python 3. + * + * When we want bytes in Python 3, we use PyBytes*_ instead of PyString_* and + * define aliases from PyBytes_* to PyString_* for Python 2. + */ + +#if PY_MAJOR_VERSION >= 3 +#define PyString_Check PyUnicode_Check +#define PyString_FromString PyUnicode_FromString +#define PyString_FromStringAndSize PyUnicode_FromStringAndSize +#define PyString_AsString(op) PyBytes_AsString(PyUnicode_AsUTF8String(op)) +#define PyInt_Check PyLong_Check +#define PyInt_AsLong PyLong_AsLong +#else +#define PyBytes_Check PyString_Check +#define PyBytes_AsString PyString_AsString +#define PyBytes_AsStringAndSize PyString_AsStringAndSize +#endif + template struct CppPyObject : public PyObject { // We are only using CppPyObject and friends as dumb structs only, ie the diff --git a/python/indexfile.cc b/python/indexfile.cc index dc55634f..bb40cdd0 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -81,7 +81,9 @@ static PyGetSetDef PackageIndexFileGetSet[] = { PyTypeObject PackageIndexFileType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgIndexFile", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/metaindex.cc b/python/metaindex.cc index efbc38af..cbaeafbd 100644 --- a/python/metaindex.cc +++ b/python/metaindex.cc @@ -59,7 +59,9 @@ static PyObject *MetaIndexRepr(PyObject *Self) PyTypeObject MetaIndexType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "metaIndex", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index 52f86228..8f56cddc 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -95,7 +95,9 @@ static PyGetSetDef PkgManagerGetSet[] = { PyTypeObject PkgManagerType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "PackageManager", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc index 577aaf1c..978de6b7 100644 --- a/python/pkgrecords.cc +++ b/python/pkgrecords.cc @@ -135,7 +135,9 @@ static PyGetSetDef PkgRecordsGetSet[] = { PyTypeObject PkgRecordsType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgRecords", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc index c830f8d2..97667d7a 100644 --- a/python/pkgsrcrecords.cc +++ b/python/pkgsrcrecords.cc @@ -183,7 +183,9 @@ static PyGetSetDef PkgSrcRecordsGetSet[] = { PyTypeObject PkgSrcRecordsType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgSrcRecords", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/sourcelist.cc b/python/sourcelist.cc index 9f8f8878..48b3b7c8 100644 --- a/python/sourcelist.cc +++ b/python/sourcelist.cc @@ -100,7 +100,9 @@ static PyGetSetDef PkgSourceListGetSet[] = { PyTypeObject PkgSourceListType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "pkgSourceList", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/string.cc b/python/string.cc index 8168ea5b..b95ee3eb 100644 --- a/python/string.cc +++ b/python/string.cc @@ -38,7 +38,21 @@ PyObject *Python(PyObject *Self,PyObject *Args) \ } MkStr(StrDeQuote,DeQuoteString); -MkStr(StrBase64Encode,Base64Encode); + +/* + * Input bytes(Py3k)/str(Py2), output str. + */ +PyObject *StrBase64Encode(PyObject *Self,PyObject *Args) { + char *Str = 0; + #if PY_MAJOR_VERSION >= 3 + if (PyArg_ParseTuple(Args,"y",&Str) == 0) + #else + if (PyArg_ParseTuple(Args,"s",&Str) == 0) + #endif + return 0; + return CppPyString(Base64Encode(Str)); +} + MkStr(StrURItoFileName,URItoFileName); //MkFloat(StrSizeToStr,SizeToStr); diff --git a/python/tag.cc b/python/tag.cc index cdea3e03..18d08580 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -384,7 +384,9 @@ PyMappingMethods TagSecMapMeth = {TagSecLength,TagSecMap,0}; PyTypeObject TagSecType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "TagSection", // tp_name sizeof(TagSecData), // tp_basicsize 0, // tp_itemsize @@ -442,7 +444,9 @@ static PyGetSetDef TagFileGetSet[] = { PyTypeObject TagFileType = { PyObject_HEAD_INIT(&PyType_Type) + #if PY_MAJOR_VERSION < 3 0, // ob_size + #endif "TagFile", // tp_name sizeof(TagFileData), // tp_basicsize 0, // tp_itemsize diff --git a/setup3.py b/setup3.py new file mode 100644 index 00000000..a3cbdc8e --- /dev/null +++ b/setup3.py @@ -0,0 +1,77 @@ +#! /usr/bin/env python3 +# $Id: setup.py,v 1.2 2002/01/08 07:13:21 jgg Exp $ +import glob +import os +import shutil +import sys + +from distutils.core import setup, Extension +from distutils.sysconfig import parse_makefile +#from DistUtilsExtra.command import build_extra, build_i18n + + +# The apt_pkg module +files = ["python/"+source for source in parse_makefile("python/makefile")["APT_PKG_SRC"].split()] +apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) + +# The apt_inst module +files = ["python/"+source for source in parse_makefile("python/makefile")["APT_INST_SRC"].split()] +apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) + +# Replace the leading _ that is used in the templates for translation +templates = [] + +# build doc +if len(sys.argv) > 1 and sys.argv[1] == "build": + if not os.path.exists("build/data/templates/"): + os.makedirs("build/data/templates") + for template in glob.glob('data/templates/*.info.in'): + source = open(template, "r") + build = open(os.path.join("build", template[:-3]), "w") + lines = source.readlines() + for line in lines: + build.write(line.lstrip("_")) + source.close() + build.close() + + +if len(sys.argv) > 1 and sys.argv[1] == "clean" and '-a' in sys.argv: + for dirname in "build/doc", "doc/build", "build/data", "build/mo": + if os.path.exists(dirname): + print("Removing", dirname) + shutil.rmtree(dirname) + else: + print("Not removing", dirname, "because it does not exist") + +setup(name="python-apt", + description="Python bindings for APT", + version=os.environ.get('DEBVER'), + author="APT Development Team", + author_email="deity@lists.debian.org", + ext_modules=[apt_pkg, apt_inst], + packages=['apt', 'apt.progress', 'aptsources'], + data_files = [('share/python-apt/templates', + glob.glob('build/data/templates/*.info')), + ('share/python-apt/templates', + glob.glob('data/templates/*.mirrors'))], +# cmdclass = {"build": build_extra.build_extra, +# "build_i18n": build_i18n.build_i18n}, + license = 'GNU GPL', + platforms = 'posix') + +if len(sys.argv) > 1 and sys.argv[1] == "build": + try: + import sphinx + except ImportError: + print(('W: Sphinx not available - Not building' + 'documentation'), file=sys.stderr) + try: + import pygtk + except ImportError: + print(('W: Not building documentation because python-' + 'gtk2 is not available at the moment.'), file=sys.stderr) + sys.exit(0) + sphinx.main(["sphinx", "-b", "html", "-d", "build/doc/doctrees", + os.path.abspath("doc/source"), "build/doc/html"]) + sphinx.main(["sphinx", "-b", "text", "-d", "build/doc/doctrees", + os.path.abspath("doc/source"), "build/doc/text"]) -- cgit v1.2.3 From b71b5243d22f75ba5df926e8086345498157032e Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Apr 2009 20:22:04 +0200 Subject: * debian/rules: Fix building. --- debian/rules | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'debian') diff --git a/debian/rules b/debian/rules index 7de945f2..9d0219e2 100755 --- a/debian/rules +++ b/debian/rules @@ -36,19 +36,19 @@ build/python-apt-dbg:: for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py build; \ done - ifeq($(PY3K),y) +ifeq ($(PY3K),y) python3.1-dbg ./setup3.py build - endif +endif install/python-apt-dbg:: for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py install --root $(CURDIR)/debian/python-apt-dbg \ --no-compile; \ done - ifeq($(PY3K),y) +ifeq ($(PY3K),y) python3.1-dbg ./setup3.py install --root $(CURDIR)/debian/python-apt-dbg \ --install-layout=deb --no-compile - endif +endif find debian/python-apt-dbg \ ! -type d ! -name '*_d.so' | xargs rm -f find debian/python-apt-dbg -depth -empty -exec rmdir {} \; -- cgit v1.2.3 From abc7c861e85265b0725aa82a51fe41f9183bc506 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Apr 2009 20:23:04 +0200 Subject: * Upload as 0.7.90 to experimental This is the first pre-release of python-apt 0.8. It is completely backward compatible (even on Python 3), API changes will appear in 0.7.91. --- debian/changelog | 2 +- doc/source/apt_inst.rst | 10 +++++----- doc/source/apt_pkg/cache.rst | 8 ++++---- doc/source/apt_pkg/index.rst | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index d356c3cf..b2f2b965 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -python-apt (0.7.11) UNRELEASED; urgency=low +python-apt (0.7.90) experimental; urgency=low * Introduce support for Python 3 (Closes: #523645) diff --git a/doc/source/apt_inst.rst b/doc/source/apt_inst.rst index 999d074e..cd371e36 100644 --- a/doc/source/apt_inst.rst +++ b/doc/source/apt_inst.rst @@ -15,7 +15,7 @@ Checking packages :class:`file()` object, a file descriptor, or anything implementing a :meth:`fileno` method. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for file descriptors and objects implementing a :meth:`fileno` method. @@ -34,7 +34,7 @@ Listing contents See :ref:`emulating-dpkg-contents` for a more detailed example. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for file descriptors and objects implementing a :meth:`fileno` method. .. function:: tarExtract(file,func,comp) @@ -47,7 +47,7 @@ Listing contents The parameter *file* may be a :class:`file()` object, a file descriptor, or anything implementing a :meth:`fileno` method. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for file descriptors and objects implementing a :meth:`fileno` method. @@ -81,7 +81,7 @@ Extracting contents If the directory given by *rootdir* does not exist, the package is extracted into the current directory. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for file descriptors and objects implementing a :meth:`fileno` method. .. function:: debExtractControl(file[, member='control']) @@ -97,7 +97,7 @@ Extracting contents print debExtractControl(open("package.deb")) - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for file descriptors and objects implementing a :meth:`fileno` method. diff --git a/doc/source/apt_pkg/cache.rst b/doc/source/apt_pkg/cache.rst index 86515569..a58f1356 100644 --- a/doc/source/apt_pkg/cache.rst +++ b/doc/source/apt_pkg/cache.rst @@ -121,7 +121,7 @@ Classes in apt_pkg Return ``True`` if *conf* has a key *key*, else ``False``. - .. versionadded:: 0.7.11 + .. versionadded:: 0.8.0 .. describe:: conf[key] @@ -207,7 +207,7 @@ Classes in apt_pkg Return whether the configuration contains the key *key*. - .. deprecated:: 0.7.11 + .. deprecated:: 0.8.0 .. method:: get(key[, default='']) @@ -1211,7 +1211,7 @@ broken dependencies: Return ``True`` if *section* has a key *key*, else ``False``. - .. versionadded:: 0.7.11 + .. versionadded:: 0.8.0 .. method:: Bytes @@ -1236,7 +1236,7 @@ broken dependencies: Check whether the field with named by *key* exists. - .. deprecated:: 0.7.11 + .. deprecated:: 0.8.0 .. method:: keys() diff --git a/doc/source/apt_pkg/index.rst b/doc/source/apt_pkg/index.rst index 60c3ba9b..47923c23 100644 --- a/doc/source/apt_pkg/index.rst +++ b/doc/source/apt_pkg/index.rst @@ -166,7 +166,7 @@ of the ones provides in Python's :mod:`hashlib` module. object (or a file descriptor), in which case the md5sum of its contents is returned. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for using file descriptors. .. function:: sha1sum(object) @@ -176,7 +176,7 @@ of the ones provides in Python's :mod:`hashlib` module. object (or a file descriptor), in which case the sha1sum of its contents is returned. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for using file descriptors. .. function:: sha256sum(object) @@ -186,7 +186,7 @@ of the ones provides in Python's :mod:`hashlib` module. object (or a file descriptor), in which case the sha256sum of its contents is returned. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for using file descriptors. Debian control files @@ -202,7 +202,7 @@ Debian control files be a :class:`file()` object, a file descriptor, or anything providing a :meth:`fileno()` method. - .. versionchanged:: 0.7.11 + .. versionchanged:: 0.8.0 Added support for using file descriptors. .. autofunction:: RewriteSection(section, order, rewrite_list) -- cgit v1.2.3 From 337c885e7dd531858c35b256d974989bac6463df Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 16 Apr 2009 20:06:14 +0200 Subject: * apt/*.py: Initial rename work for Bug#481061 A new module, apt.deprecation, is introduced containing functions and classes which assist in the deprecation. The apt_pkg extension gets a new attribute, _COMPAT_0_7 which can be set by defining COMPAT_0_7 at compile time (-DCOMPAT_0_7). The names are changed, and compatibility functions are enabled if bool(apt_pkg._COMPAT_0_7) == True, i.e. if the package has been built with backward compatibility fixes. This commit changes the apt and aptsources packages, the apt_pkg and apt_inst extensions will be the next renames. --- apt/__init__.py | 15 ++++-- apt/cache.py | 108 +++++++++++++++++++++++++-------------- apt/cdrom.py | 6 ++- apt/debfile.py | 32 ++++++------ apt/deprecation.py | 76 ++++++++++++++++++++++++++++ apt/package.py | 126 +++++++++++++++++++++++++++++++--------------- apt/progress/gtk2.py | 6 +-- aptsources/sourceslist.py | 6 ++- debian/changelog | 6 +++ debian/control | 2 +- debian/rules | 3 ++ po/python-apt.pot | 10 ++-- python/apt_pkgmodule.cc | 6 +++ 13 files changed, 290 insertions(+), 112 deletions(-) create mode 100644 apt/deprecation.py (limited to 'debian') diff --git a/apt/__init__.py b/apt/__init__.py index ae2abbf2..734b3240 100644 --- a/apt/__init__.py +++ b/apt/__init__.py @@ -17,17 +17,21 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA # import the core of apt_pkg +"""High-Level Interface for working with apt.""" import apt_pkg -import sys -import os # import some fancy classes from apt.package import Package from apt.cache import Cache -from apt.progress import ( - OpProgress, FetchProgress, InstallProgress, CdromProgress) from apt.cdrom import Cdrom -from apt_pkg import SizeToStr, TimeToStr, VersionCompare + +if apt_pkg._COMPAT_0_7: + from apt.progress import (OpProgress, FetchProgress, InstallProgress, + CdromProgress) + + +if apt_pkg._COMPAT_0_7: + from apt_pkg import SizeToStr, TimeToStr, VersionCompare # init the package system apt_pkg.init() @@ -36,3 +40,4 @@ apt_pkg.init() #import warnings #warnings.warn("apt API not stable yet", FutureWarning) #del warnings +__all__ = ['Cache', 'Cdrom', 'Package'] diff --git a/apt/cache.py b/apt/cache.py index d13010af..928322d2 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -24,6 +24,7 @@ import weakref import apt_pkg from apt import Package +from apt.deprecation import AttributeDeprecatedBy, function_deprecated_by import apt.progress @@ -63,7 +64,7 @@ class Cache(object): rootdir + "/var/lib/dpkg/status") self.open(progress) - def _runCallbacks(self, name): + def _run_callbacks(self, name): """ internal helper to run a callback """ if name in self._callbacks: for callback in self._callbacks[name]: @@ -75,7 +76,7 @@ class Cache(object): """ if progress is None: progress = apt.progress.OpProgress() - self._runCallbacks("cache_pre_open") + self._run_callbacks("cache_pre_open") self._cache = apt_pkg.GetCache(progress) self._depcache = apt_pkg.GetDepCache(self._cache) self._records = apt_pkg.GetPkgRecords(self._cache) @@ -98,7 +99,7 @@ class Cache(object): i += 1 progress.done() - self._runCallbacks("cache_post_open") + self._run_callbacks("cache_post_open") def __getitem__(self, key): """ look like a dictionary (get key) """ @@ -128,12 +129,12 @@ class Cache(object): def keys(self): return list(self._set) - def getChanges(self): + def get_changes(self): """ Get the marked changes """ changes = [] for p in self: - if p.markedUpgrade or p.markedInstall or p.markedDelete or \ - p.markedDowngrade or p.markedReinstall: + if p.marked_upgrade or p.marked_install or p.marked_delete or \ + p.marked_downgrade or p.marked_reinstall: changes.append(p) return changes @@ -141,12 +142,12 @@ class Cache(object): """ Upgrade the all package, DistUpgrade will also install new dependencies """ - self.cachePreChange() + self.cache_pre_change() self._depcache.Upgrade(distUpgrade) - self.cachePostChange() + self.cache_post_change() @property - def requiredDownload(self): + def required_download(self): """Get the size of the packages that are required to download.""" pm = apt_pkg.GetPackageManager(self._depcache) fetcher = apt_pkg.GetAcquire() @@ -154,12 +155,12 @@ class Cache(object): return fetcher.FetchNeeded @property - def additionalRequiredSpace(self): + def required_space(self): """Get the size of the additional required space on the fs.""" return self._depcache.UsrSize @property - def reqReinstallPkgs(self): + def req_reinstall_pkgs(self): """Return the packages not downloadable packages in reqreinst state.""" reqreinst = set() for pkg in self: @@ -169,7 +170,7 @@ class Cache(object): reqreinst.add(pkg.name) return reqreinst - def _runFetcher(self, fetcher): + def _run_fetcher(self, fetcher): # do the actual fetching res = fetcher.Run() @@ -194,7 +195,7 @@ class Cache(object): raise FetchFailedException(errMsg) return res - def _fetchArchives(self, fetcher, pm): + def _fetch_archives(self, fetcher, pm): """ fetch the needed archives """ # get lock @@ -209,16 +210,16 @@ class Cache(object): return False # now run the fetcher, throw exception if something fails to be # fetched - return self._runFetcher(fetcher) + return self._run_fetcher(fetcher) finally: os.close(lock) - def isVirtualPackage(self, pkgname): + def is_virtual_package(self, pkgname): """Return whether the package is a virtual package.""" pkg = self._cache[pkgname] return bool(pkg.ProvidesList and not pkg.VersionList) - def getProvidingPackages(self, virtual): + def get_providing_packages(self, virtual): """ Return a list of packages which provide the virtual package of the specified name @@ -254,10 +255,16 @@ class Cache(object): finally: os.close(lock) - def installArchives(self, pm, installProgress): - installProgress.startUpdate() + def install_archives(self, pm, installProgress): + try: + installProgress.start_update() + except AttributeError: + installProgress.startUpdate() res = installProgress.run(pm) - installProgress.finishUpdate() + try: + installProgress.finish_update() + except AttributeError: + installProgress.finishUpdate() return res def commit(self, fetchProgress=None, installProgress=None): @@ -278,10 +285,10 @@ class Cache(object): fetcher = apt_pkg.GetAcquire(fetchProgress) while True: # fetch archives first - res = self._fetchArchives(fetcher, pm) + res = self._fetch_archives(fetcher, pm) # then install - res = self.installArchives(pm, installProgress) + res = self.install_archives(pm, installProgress) if res == pm.ResultCompleted: break if res == pm.ResultFailed: @@ -296,14 +303,14 @@ class Cache(object): # cache changes - def cachePostChange(self): + def cache_post_change(self): " called internally if the cache has changed, emit a signal then " - self._runCallbacks("cache_post_change") + self._run_callbacks("cache_post_change") - def cachePreChange(self): + def cache_pre_change(self): """ called internally if the cache is about to change, emit a signal then """ - self._runCallbacks("cache_pre_change") + self._run_callbacks("cache_pre_change") def connect(self, name, callback): """ connect to a signal, currently only used for @@ -312,6 +319,20 @@ class Cache(object): self._callbacks[name] = [] self._callbacks[name].append(callback) + if apt_pkg._COMPAT_0_7: + _runCallbacks = function_deprecated_by(_run_callbacks) + getChanges = function_deprecated_by(get_changes) + requiredDownload = AttributeDeprecatedBy('required_download') + additionalRequiredSpace = AttributeDeprecatedBy('required_space') + reqReinstallPkgs = AttributeDeprecatedBy('req_reinstall_pkgs') + _runFetcher = function_deprecated_by(_run_fetcher) + _fetchArchives = function_deprecated_by(_fetch_archives) + isVirtualPackage = function_deprecated_by(is_virtual_package) + getProvidingPackages = function_deprecated_by(get_providing_packages) + installArchives = function_deprecated_by(install_archives) + cachePostChange = function_deprecated_by(cache_post_change) + cachePreChange = function_deprecated_by(cache_pre_change) + # ----------------------------- experimental interface @@ -330,7 +351,7 @@ class MarkedChangesFilter(Filter): """ Filter that returns all marked changes """ def apply(self, pkg): - if pkg.markedInstall or pkg.markedDelete or pkg.markedUpgrade: + if pkg.marked_install or pkg.marked_delete or pkg.marked_upgrade: return True else: return False @@ -347,8 +368,8 @@ class FilteredCache(object): self.cache = Cache(progress) else: self.cache = cache - self.cache.connect("cache_post_change", self.filterCachePostChange) - self.cache.connect("cache_post_open", self.filterCachePostChange) + self.cache.connect("cache_post_change", self.filter_cache_post_change) + self.cache.connect("cache_post_open", self.filter_cache_post_change) self._filtered = {} self._filters = [] @@ -371,7 +392,7 @@ class FilteredCache(object): def __contains__(self, key): return (key in self._filtered) - def _reapplyFilter(self): + def _reapply_filter(self): " internal helper to refilter " self._filtered = {} for pkg in self.cache: @@ -380,18 +401,19 @@ class FilteredCache(object): self._filtered[pkg.name] = 1 break - def setFilter(self, filter): + def set_filter(self, filter): """Set the current active filter.""" self._filters = [] self._filters.append(filter) #self._reapplyFilter() # force a cache-change event that will result in a refiltering - self.cache.cachePostChange() + self.cache.cache_post_change() - def filterCachePostChange(self): + def filter_cache_post_change(self): """Called internally if the cache changes, emit a signal then.""" #print "filterCachePostChange()" - self._reapplyFilter() + self._reapply_filter() + # def connect(self, name, callback): # self.cache.connect(name, callback) @@ -401,6 +423,12 @@ class FilteredCache(object): #print "getattr: %s " % key return getattr(self.cache, key) + if apt_pkg._COMPAT_0_7: + _reapplyFilter = function_deprecated_by(_reapply_filter) + setFilter = function_deprecated_by(set_filter) + filterCachePostChange = function_deprecated_by(\ + filter_cache_post_change) + def cache_pre_changed(): print "cache pre changed" @@ -410,8 +438,8 @@ def cache_post_changed(): print "cache post changed" -# internal test code -if __name__ == "__main__": +def _test(): + """Internal test code.""" print "Cache self test" apt_pkg.init() c = Cache(apt.progress.OpTextProgress()) @@ -426,7 +454,7 @@ if __name__ == "__main__": x= c[pkg].name c.upgrade() - changes = c.getChanges() + changes = c.get_changes() print len(changes) for p in changes: #print p.name @@ -440,7 +468,7 @@ if __name__ == "__main__": apt_pkg.Config.Set("Dir::Cache::Archives", "/tmp/pytest") pm = apt_pkg.GetPackageManager(c._depcache) fetcher = apt_pkg.GetAcquire(apt.progress.TextFetchProgress()) - c._fetchArchives(fetcher, pm) + c._fetch_archives(fetcher, pm) #sys.exit(1) print "Testing filtered cache (argument is old cache)" @@ -448,7 +476,7 @@ if __name__ == "__main__": f.cache.connect("cache_pre_change", cache_pre_changed) f.cache.connect("cache_post_change", cache_post_changed) f.cache.upgrade() - f.setFilter(MarkedChangesFilter()) + f.set_filter(MarkedChangesFilter()) print len(f) for pkg in f.keys(): #print c[pkg].name @@ -461,10 +489,12 @@ if __name__ == "__main__": f.cache.connect("cache_pre_change", cache_pre_changed) f.cache.connect("cache_post_change", cache_post_changed) f.cache.upgrade() - f.setFilter(MarkedChangesFilter()) + f.set_filter(MarkedChangesFilter()) print len(f) for pkg in f.keys(): #print c[pkg].name x = f[pkg].name print len(f) +if __name__ == '__main__': + _test() diff --git a/apt/cdrom.py b/apt/cdrom.py index b52762ad..907ac622 100644 --- a/apt/cdrom.py +++ b/apt/cdrom.py @@ -24,6 +24,7 @@ import glob import apt_pkg from apt.progress import CdromProgress +from apt.deprecation import AttributeDeprecatedBy class Cdrom(object): @@ -69,7 +70,7 @@ class Cdrom(object): return ident @property - def inSourcesList(self): + def in_sources_list(self): """Check if the cdrom is already in the current sources.list.""" cd_id = self.ident() if cd_id is None: @@ -84,3 +85,6 @@ class Cdrom(object): if not line.lstrip().startswith("#") and cd_id in line: return True return False + + if apt_pkg._COMPAT_0_7: + inSourcesList = AttributeDeprecatedBy('in_sources_list') diff --git a/apt/debfile.py b/apt/debfile.py index 8d4f534c..c60fc92d 100644 --- a/apt/debfile.py +++ b/apt/debfile.py @@ -97,11 +97,11 @@ class DebPackage(object): # check for virtual pkgs if not depname in self._cache: - if self._cache.isVirtualPackage(depname): + if self._cache.is_virtual_package(depname): self._dbg(3, "_isOrGroupSatisfied(): %s is virtual dep" % depname) - for pkg in self._cache.getProvidingPackages(depname): - if pkg.isInstalled: + for pkg in self._cache.get_providing_packages(depname): + if pkg.is_installed: return True continue @@ -117,9 +117,9 @@ class DebPackage(object): # if we don't have it in the cache, it may be virtual if not depname in self._cache: - if not self._cache.isVirtualPackage(depname): + if not self._cache.is_virtual_package(depname): continue - providers = self._cache.getProvidingPackages(depname) + providers = self._cache.get_providing_packages(depname) # if a package just has a single virtual provider, we # just pick that (just like apt) if len(providers) != 1: @@ -158,9 +158,9 @@ class DebPackage(object): (pkgname, ver, oper)) pkg = self._cache[pkgname] - if pkg.isInstalled: + if pkg.is_installed: pkgver = pkg.installed.version - elif pkg.markedInstall: + elif pkg.marked_install: pkgver = pkg.candidate.version else: return False @@ -191,8 +191,8 @@ class DebPackage(object): if not depname in self._cache: # FIXME: we have to check for virtual replaces here as # well (to pass tests/gdebi-test8.deb) - if self._cache.isVirtualPackage(depname): - for pkg in self._cache.getProvidingPackages(depname): + if self._cache.is_virtual_package(depname): + for pkg in self._cache.get_providing_packages(depname): self._dbg(3, "conflicts virtual check: %s" % pkg.name) # P/C/R on virtal pkg, e.g. ftpd if self.pkgname == pkg.name: @@ -253,9 +253,9 @@ class DebPackage(object): """ self._dbg(3, "replacesPkg() %s %s %s" % (pkgname, oper, ver)) pkg = self._cache[pkgname] - if pkg.isInstalled: + if pkg.is_installed: pkgver = pkg.installed.version - elif pkg.markedInstall: + elif pkg.marked_install: pkgver = pkg.candidate.version else: pkgver = None @@ -371,7 +371,7 @@ class DebPackage(object): # now try it out in the cache for pkg in self._need_pkgs: try: - self._cache[pkg].markInstall(fromUser=False) + self._cache[pkg].mark_install(fromUser=False) except SystemError, e: self._failure_string = _("Cannot install '%s'" % pkg) self._cache.clear() @@ -396,7 +396,7 @@ class DebPackage(object): remove = [] unauthenticated = [] for pkg in self._cache: - if pkg.markedInstall or pkg.markedUpgrade: + if pkg.marked_install or pkg.marked_upgrade: install.append(pkg.name) # check authentication, one authenticated origin is enough # libapt will skip non-authenticated origins then @@ -405,7 +405,7 @@ class DebPackage(object): authenticated |= origin.trusted if not authenticated: unauthenticated.append(pkg.name) - if pkg.markedDelete: + if pkg.marked_delete: remove.append(pkg.name) return (install, remove, unauthenticated) @@ -492,7 +492,7 @@ class DscSrcPackage(DebPackage): for pkgname in self._installed_conflicts: if self._cache[pkgname]._pkg.Essential: raise Exception(_("An essential package would be removed")) - self._cache[pkgname].markDelete() + self._cache[pkgname].mark_delete() # FIXME: a additional run of the checkConflicts() # after _satisfyDepends() should probably be done return self._satisfy_depends(self.depends) @@ -507,7 +507,7 @@ def _test(): vp = "www-browser" #print "%s virtual: %s" % (vp, cache.isVirtualPackage(vp)) - providers = cache.getProvidingPackages(vp) + providers = cache.get_providing_packages(vp) print "Providers for %s :" % vp for pkg in providers: print " %s" % pkg.name diff --git a/apt/deprecation.py b/apt/deprecation.py new file mode 100644 index 00000000..a14d49e6 --- /dev/null +++ b/apt/deprecation.py @@ -0,0 +1,76 @@ +# deprecation.py - Module providing classes and functions for deprecation. +# +# Copyright (c) 2009 Julian Andres Klode +# Copyright (c) 2009 Ben Finney +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +"""Classes and functions for deprecating features. + +This is used for internal purposes only and not part of the official API. Do +not use it for anything outside the apt package. +""" +import re +import operator +import warnings + +__all__ = [] + + +class AttributeDeprecatedBy(object): + """Property acting as a proxy for a new attribute. + + When accessed, the property issues a DeprecationWarning and (on get) calls + attrgetter() for the attribute 'attribute' on the current object or (on + set) uses setattr to set the value of the wrapped attribute. + """ + + def __init__(self, attribute): + """Initialize the property.""" + self.attribute = attribute + self.__doc__ = 'Deprecated, please use \'%s\' instead' % attribute + self.getter = operator.attrgetter(attribute) + + def __get__(self, obj, type=None): + """Issue a DeprecationWarning and return the requested value.""" + if obj is None: + return getattr(type, self.attribute, self) + warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2) + return self.getter(obj or type) + + def __set__(self, obj, value): + """Issue a DeprecationWarning and set the requested value.""" + warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2) + setattr(obj, self.attribute, value) + + +def function_deprecated_by(func, convert_names=True): + """Return a function that warns it is deprecated by another function. + + Returns a new function that warns it is deprecated by function 'func', + then acts as a pass-through wrapper for 'func'. + + This function also converts all keyword argument names from mixedCase to + lowercase_with_underscores, but only if 'convert_names' is True (default). + """ + warning = 'Deprecated, please use \'%s\' instead' % func.func_name + + def deprecated_function(*args, **kwds): + warnings.warn(warning, DeprecationWarning, stacklevel=2) + if convert_names: + for key in kwds.keys(): + kwds[re.sub('([A-Z])', '_\\1', key).lower()] = kwds.pop(key) + return func(*args, **kwds) + return deprecated_function diff --git a/apt/package.py b/apt/package.py index db5696ae..70997383 100644 --- a/apt/package.py +++ b/apt/package.py @@ -31,6 +31,7 @@ import warnings import apt_pkg import apt.progress +from apt.deprecation import function_deprecated_by, AttributeDeprecatedBy __all__ = ('BaseDependency', 'Dependency', 'Origin', 'Package', 'Record', 'Version') @@ -56,21 +57,24 @@ class BaseDependency(object): """A single dependency. Attributes defined here: - name - The name of the dependency - relation - The relation (>>,>=,==,<<,<=,) - version - The version depended on - preDepend - Boolean value whether this is a pre-dependency. + name - The name of the dependency + relation - The relation (>>,>=,==,<<,<=,) + version - The version depended on + pre_depend - Boolean value whether this is a pre-dependency. """ def __init__(self, name, rel, ver, pre): self.name = name self.relation = rel self.version = ver - self.preDepend = pre + self.pre_depend = pre def __repr__(self): return ('' - % (self.name, self.relation, self.version, self.preDepend)) + % (self.name, self.relation, self.version, self.pre_depend)) + + if apt_pkg._COMPAT_0_7: + preDepend = AttributeDeprecatedBy('pre_depend') class Dependency(object): @@ -103,7 +107,7 @@ class DeprecatedProperty(property): warnings.warn("Accessed deprecated property %s.%s, please see the " "Version class for alternatives." % ((obj.__class__.__name__ or type.__name__), - self.fget.func_name), DeprecationWarning, 2) + self.fget.__name__), DeprecationWarning, 2) return property.__get__(self, obj, type) @@ -528,9 +532,9 @@ class Package(object): def __set_candidate(self, version): """Set the candidate version of the package.""" - self._pcache.cachePreChange() + self._pcache.cache_pre_change() self._pcache._depcache.SetCandidateVer(self._pkg, version._cand) - self._pcache.cachePostChange() + self._pcache.cache_post_change() candidate = property(candidate, __set_candidate) @@ -703,55 +707,56 @@ class Package(object): # depcache states @property - def markedInstall(self): + def marked_install(self): """Return ``True`` if the package is marked for install.""" return self._pcache._depcache.MarkedInstall(self._pkg) @property - def markedUpgrade(self): + def marked_upgrade(self): """Return ``True`` if the package is marked for upgrade.""" return self._pcache._depcache.MarkedUpgrade(self._pkg) @property - def markedDelete(self): + def marked_delete(self): """Return ``True`` if the package is marked for delete.""" return self._pcache._depcache.MarkedDelete(self._pkg) @property - def markedKeep(self): + def marked_keep(self): """Return ``True`` if the package is marked for keep.""" return self._pcache._depcache.MarkedKeep(self._pkg) @property - def markedDowngrade(self): + def marked_downgrade(self): """ Package is marked for downgrade """ return self._pcache._depcache.MarkedDowngrade(self._pkg) @property - def markedReinstall(self): + def marked_reinstall(self): """Return ``True`` if the package is marked for reinstall.""" return self._pcache._depcache.MarkedReinstall(self._pkg) @property - def isInstalled(self): + def is_installed(self): """Return ``True`` if the package is installed.""" return (self._pkg.CurrentVer is not None) @property - def isUpgradable(self): + def is_upgradable(self): """Return ``True`` if the package is upgradable.""" - return (self.isInstalled and + return (self.is_installed and self._pcache._depcache.IsUpgradable(self._pkg)) @property - def isAutoRemovable(self): + def is_auto_removable(self): """Return ``True`` if the package is no longer required. If the package has been installed automatically as a dependency of another package, and if no packages depend on it anymore, the package is no longer required. """ - return self.isInstalled and self._pcache._depcache.IsGarbage(self._pkg) + return self.is_installed and \ + self._pcache._depcache.IsGarbage(self._pkg) # sizes @@ -789,7 +794,7 @@ class Package(object): return getattr(self.installed, 'installed_size', 0) @property - def installedFiles(self): + def installed_files(self): """Return a list of files installed by the package. Return a list of unicode names of the files which have @@ -805,7 +810,7 @@ class Package(object): except EnvironmentError: return [] - def getChangelog(self, uri=None, cancel_lock=None): + def get_changelog(self, uri=None, cancel_lock=None): """ Download the changelog of the package and return it as unicode string. @@ -928,7 +933,7 @@ class Package(object): if match: # strip epoch from installed version # and from changelog too - installed = self.installedVersion + installed = getattr(self.installed, 'version', None) if installed and ":" in installed: installed = installed.split(":", 1)[1] changelog_ver = match.group(1) @@ -976,13 +981,13 @@ class Package(object): # depcache actions - def markKeep(self): + def mark_keep(self): """Mark a package for keep.""" - self._pcache.cachePreChange() + self._pcache.cache_pre_change() self._pcache._depcache.MarkKeep(self._pkg) - self._pcache.cachePostChange() + self._pcache.cache_post_change() - def markDelete(self, autoFix=True, purge=False): + def mark_delete(self, autoFix=True, purge=False): """Mark a package for install. If *autoFix* is ``True``, the resolver will be run, trying to fix @@ -991,7 +996,7 @@ class Package(object): If *purge* is ``True``, remove the configuration files of the package as well. The default is to keep the configuration. """ - self._pcache.cachePreChange() + self._pcache.cache_pre_change() self._pcache._depcache.MarkDelete(self._pkg, purge) # try to fix broken stuffsta if autoFix and self._pcache._depcache.BrokenCount > 0: @@ -1001,9 +1006,9 @@ class Package(object): Fix.Remove(self._pkg) Fix.InstallProtect() Fix.Resolve() - self._pcache.cachePostChange() + self._pcache.cache_post_change() - def markInstall(self, autoFix=True, autoInst=True, fromUser=True): + def mark_install(self, autoFix=True, autoInst=True, fromUser=True): """Mark a package for install. If *autoFix* is ``True``, the resolver will be run, trying to fix @@ -1017,7 +1022,7 @@ class Package(object): want to be able to automatically remove the package at a later stage when no other package depends on it. """ - self._pcache.cachePreChange() + self._pcache.cache_pre_change() self._pcache._depcache.MarkInstall(self._pkg, autoInst, fromUser) # try to fix broken stuff if autoFix and self._pcache._depcache.BrokenCount > 0: @@ -1025,12 +1030,12 @@ class Package(object): fixer.Clear(self._pkg) fixer.Protect(self._pkg) fixer.Resolve(True) - self._pcache.cachePostChange() + self._pcache.cache_post_change() - def markUpgrade(self): + def mark_upgrade(self): """Mark a package for upgrade.""" - if self.isUpgradable: - self.markInstall() + if self.is_upgradable: + self.mark_install() else: # FIXME: we may want to throw a exception here sys.stderr.write(("MarkUpgrade() called on a non-upgrable pkg: " @@ -1048,11 +1053,50 @@ class Package(object): self._pcache._depcache.Commit(fprogress, iprogress) + if not apt_pkg._COMPAT_0_7: + del installedVersion + del candidateVersion + del candidateDependencies + del installedDependencies + del architecture + del candidateDownloadable + del installedDownloadable + del sourcePackageName + del homepage + del priority + del installedPriority + del summary + del description + del rawDescription + del candidateRecord + del installedRecord + del packageSize + del installedPackageSize + del candidateInstalledSize + del installedSize + del candidateOrigin + else: + markedInstalled = AttributeDeprecatedBy('marked_installed') + markedUpgrade = AttributeDeprecatedBy('marked_upgrade') + markedDelete = AttributeDeprecatedBy('marked_delete') + markedKeep = AttributeDeprecatedBy('marked_keep') + markedDowngrade = AttributeDeprecatedBy('marked_downgrade') + markedReinstall = AttributeDeprecatedBy('marked_reinstall') + isInstalled = AttributeDeprecatedBy('is_installed') + isUpgradable = AttributeDeprecatedBy('is_upgradable') + isAutoRemovable = AttributeDeprecatedBy('is_auto_removable') + installedFiles = AttributeDeprecatedBy('installed_files') + getChangelog = function_deprecated_by(get_changelog) + markDelete = function_deprecated_by(mark_delete) + markInstall = function_deprecated_by(mark_install) + markKeep = function_deprecated_by(mark_keep) + markUpgrade = function_deprecated_by(mark_upgrade) + + def _test(): """Self-test.""" print "Self-test for the Package modul" import random - import apt apt_pkg.init() progress = apt.progress.OpTextProgress() cache = apt.Cache(progress) @@ -1075,19 +1119,19 @@ def _test(): print "Dependencies: %s" % pkg.installed.dependencies for dep in pkg.candidate.dependencies: print ",".join("%s (%s) (%s) (%s)" % (o.name, o.version, o.relation, - o.preDepend) for o in dep.or_dependencies) + o.pre_depend) for o in dep.or_dependencies) print "arch: %s" % pkg.candidate.architecture print "homepage: %s" % pkg.candidate.homepage print "rec: ", pkg.candidate.record - print cache["2vcard"].getChangelog() + print cache["2vcard"].get_changelog() for i in True, False: print "Running install on random upgradable pkgs with AutoFix: %s " % i for pkg in cache: - if pkg.isUpgradable: + if pkg.is_upgradable: if random.randint(0, 1) == 1: - pkg.markInstall(i) + pkg.mark_install(i) print "Broken: %s " % cache._depcache.BrokenCount print "InstCount: %s " % cache._depcache.InstCount @@ -1099,7 +1143,7 @@ def _test(): for name in cache.keys(): if random.randint(0, 1) == 1: try: - cache[name].markDelete(i) + cache[name].mark_delete(i) except SystemError: print "Error trying to remove: %s " % name print "Broken: %s " % cache._depcache.BrokenCount diff --git a/apt/progress/gtk2.py b/apt/progress/gtk2.py index f872e34f..36d459bc 100644 --- a/apt/progress/gtk2.py +++ b/apt/progress/gtk2.py @@ -422,10 +422,10 @@ def _test(): win.show() cache = apt.cache.Cache(apt_progress.open) pkg = cache["xterm"] - if pkg.isInstalled: - pkg.markDelete() + if pkg.is_installed: + pkg.mark_delete() else: - pkg.markInstall() + pkg.mark_install() apt_progress.show_terminal(True) try: cache.commit(apt_progress.fetch, apt_progress.install) diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py index 1dfd870f..fdc0f029 100644 --- a/aptsources/sourceslist.py +++ b/aptsources/sourceslist.py @@ -33,6 +33,7 @@ import time import apt_pkg from aptsources.distinfo import DistInfo +from apt.deprecation import function_deprecated_by # some global helpers @@ -309,7 +310,7 @@ class SourcesList(object): """ remove the specified entry from the sources.list """ self.list.remove(source_entry) - def restoreBackup(self, backup_ext): + def restore_backup(self, backup_ext): " restore sources.list files based on the backup extension " file = apt_pkg.Config.FindFile("Dir::Etc::sourcelist") if os.path.exists(file+backup_ext) and \ @@ -321,6 +322,9 @@ class SourcesList(object): if os.path.exists(file+backup_ext): shutil.copy(file+backup_ext, file) + if apt_pkg._COMPAT_0_7: + restoreBackup = function_deprecated_by(restore_backup) + def backup(self, backup_ext=None): """ make a backup of the current source files, if no backup extension is given, the current date/time is used (and returned) """ diff --git a/debian/changelog b/debian/changelog index b2f2b965..e344c145 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +python-apt (0.7.91) UNRELEASED; urgency=low + + * Rename all methods,functions,attributes to conform to PEP 8 (Closes: #481061) + + -- Julian Andres Klode Thu, 16 Apr 2009 18:54:29 +0200 + python-apt (0.7.90) experimental; urgency=low * Introduce support for Python 3 (Closes: #523645) diff --git a/debian/control b/debian/control index 08ee329f..374a177c 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: APT Development Team Uploaders: Michael Vogt , Julian Andres Klode Standards-Version: 3.8.1 -XS-Python-Version: all +XS-Python-Version: >= 2.5 Build-Depends: apt-utils, cdbs, debhelper (>= 5.0.37.1), diff --git a/debian/rules b/debian/rules index 9d0219e2..5fc6e13b 100755 --- a/debian/rules +++ b/debian/rules @@ -16,6 +16,9 @@ PKG=python-apt DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS) + +# Define COMPAT_0_7 to get all the deprecated interfaces. +export CFLAGS+=-DCOMPAT_0_7 export DEBVER diff --git a/po/python-apt.pot b/po/python-apt.pot index d12ae967..3fcd395a 100644 --- a/po/python-apt.pot +++ b/po/python-apt.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-04-15 16:10+0200\n" +"POT-Creation-Date: 2009-04-16 19:54+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -354,16 +354,16 @@ msgstr "" msgid "Complete" msgstr "" -#: ../apt/package.py:282 +#: ../apt/package.py:286 #, python-format msgid "Invalid unicode in description for '%s' (%s). Please report." msgstr "" -#: ../apt/package.py:830 ../apt/package.py:934 +#: ../apt/package.py:846 ../apt/package.py:950 msgid "The list of changes is not available" msgstr "" -#: ../apt/package.py:938 +#: ../apt/package.py:954 #, python-format msgid "" "The list of changes is not available yet.\n" @@ -372,7 +372,7 @@ msgid "" "until the changes become available or try again later." msgstr "" -#: ../apt/package.py:944 +#: ../apt/package.py:960 msgid "" "Failed to download the list of changes. \n" "Please check your Internet connection." diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 3beec747..a056b0bc 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -589,6 +589,12 @@ extern "C" void initapt_pkg() AddInt(Dict,"InstStateReInstReq",pkgCache::State::ReInstReq); AddInt(Dict,"InstStateHold",pkgCache::State::Hold); AddInt(Dict,"InstStateHoldReInstReq",pkgCache::State::HoldReInstReq); + + #ifdef COMPAT_0_7 + AddInt(Dict,"_COMPAT_0_7",1); + #else + AddInt(Dict,"_COMPAT_0_7",0); + #endif #if PY_MAJOR_VERSION >= 3 return Module; #endif -- cgit v1.2.3 From 6bc61a050bd278b28e883b91cfa5999a7cf76d9d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 17 Apr 2009 18:01:30 +0200 Subject: * apt/package.py: Where possible, derive apt.package.Record from collections.Mapping. This works on Python 2.6 and newer and enhances the Record class with some new methods on these platforms, e.g. keys(). --- apt/package.py | 13 ++++++++++++- debian/changelog | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'debian') diff --git a/apt/package.py b/apt/package.py index 1a2626fa..411f9635 100644 --- a/apt/package.py +++ b/apt/package.py @@ -28,6 +28,11 @@ import socket import subprocess import urllib2 import warnings +try: + from collections import Mapping +except ImportError: + # (for Python < 2.6) pylint: disable-msg=C0103 + Mapping = object import apt_pkg import apt.progress @@ -145,7 +150,7 @@ class Origin(object): self.site, self.trusted) -class Record(object): +class Record(Mapping): """Represent a pkgRecord. It can be accessed like a dictionary and can also give the original package @@ -155,6 +160,9 @@ class Record(object): def __init__(self, record_str): self._rec = apt_pkg.ParseSection(record_str) + def __hash__(self): + return hash(self._rec) + def __str__(self): return str(self._rec) @@ -183,6 +191,9 @@ class Record(object): """deprecated form of ``key in x``.""" return key in self._rec + def __len__(self): + return len(self._rec) + class Version(object): """Representation of a package version. diff --git a/debian/changelog b/debian/changelog index e344c145..e8e14306 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ python-apt (0.7.91) UNRELEASED; urgency=low * Rename all methods,functions,attributes to conform to PEP 8 (Closes: #481061) + * Where possible, derive apt.package.Record from collections.Mapping. - -- Julian Andres Klode Thu, 16 Apr 2009 18:54:29 +0200 + -- Julian Andres Klode Fri, 17 Apr 2009 17:48:27 +0200 python-apt (0.7.90) experimental; urgency=low -- cgit v1.2.3 From a7026989dd1ea3b70cbfc80cf92077efb2f52ba3 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 19 Apr 2009 15:57:07 +0200 Subject: ActionGroups can be used as a context manager for the 'with' statement. --- debian/changelog | 1 + python/depcache.cc | 32 +++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index e8e14306..30d54a29 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ python-apt (0.7.91) UNRELEASED; urgency=low * Rename all methods,functions,attributes to conform to PEP 8 (Closes: #481061) * Where possible, derive apt.package.Record from collections.Mapping. + * ActionGroups can be used as a context manager for the 'with' statement. -- Julian Andres Klode Fri, 17 Apr 2009 17:48:27 +0200 diff --git a/python/depcache.cc b/python/depcache.cc index 0cadee64..70d5af4e 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -852,9 +852,24 @@ static PyObject *PkgActionGroupRelease(PyObject *Self,PyObject *Args) return HandleErrors(Py_None); } +static PyObject *PkgActionGroupEnter(PyObject *Self,PyObject *Args) { + if (PyArg_ParseTuple(Args,"") == 0) + return 0; + return Self; +} +static PyObject *PkgActionGroupExit(PyObject *Self,PyObject *Args) { + pkgDepCache::ActionGroup *ag = GetCpp(Self); + ag->release(); + Py_RETURN_FALSE; +} + static PyMethodDef PkgActionGroupMethods[] = { {"release", PkgActionGroupRelease, METH_VARARGS, "release()"}, + {"__exit__", PkgActionGroupExit, METH_VARARGS, "__exit__(...) -> " + "Release the action group, for 'with' statement."}, + {"__enter__", PkgActionGroupEnter, METH_VARARGS, "__enter__() -> " + "Enter, for the 'with' statement. Does nothing."}, {} }; @@ -879,11 +894,18 @@ static PyObject *PkgActionGroupNew(PyTypeObject *type,PyObject *Args,PyObject *k } static const char *doc_PkgActionGroup = "ActionGroup(depcache)\n\n" - "Create a new ActionGroup() object. ActionGroups disable certain cleanup\n" - "actions, so modifying many packages is much faster.\n\n" - "Creating an ActionGroup() makes it active, use release() to disable it\n" - "again.\n\n" - "The parameter *depcache* refers to an apt_pkg.DepCache() object."; + "Create a new ActionGroup() object. The parameter *depcache* refers to an\n" + "apt_pkg.DepCache() object.\n\n" + "ActionGroups disable certain cleanup actions, so modifying many packages\n" + "is much faster.\n\n" + "ActionGroup() can also be used with the 'with' statement, but be aware\n" + "that the ActionGroup() is active as soon as it is created, and not just\n" + "when entering the context. This means you can write::\n\n" + " with apt_pkg.ActionGroup(depcache):\n" + " depcache.markInstall(pkg)\n\n" + "Once the block of the with statement is left, the action group is \n" + "automatically released from the cache."; + PyTypeObject PkgActionGroupType = { -- cgit v1.2.3 From bd47802c98f30f67b323b0796ff5d79a5e308c08 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 20 Apr 2009 19:26:05 +0200 Subject: * utils/migrate-0.8.py: Helper to check Python code for deprecated functions, attributes, etc. Has to be run from the python-apt source tree, but can be used for all Python code using python-apt. The output may not be completely correct, but false positives are better than not checking the code. --- debian/changelog | 3 + utils/migrate-0.8.py | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100755 utils/migrate-0.8.py (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 30d54a29..f2d57afa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,9 @@ python-apt (0.7.91) UNRELEASED; urgency=low * Rename all methods,functions,attributes to conform to PEP 8 (Closes: #481061) * Where possible, derive apt.package.Record from collections.Mapping. * ActionGroups can be used as a context manager for the 'with' statement. + * utils/migrate-0.8.py: Helper to check Python code for deprecated functions, + attributes,etc. Has to be run from the python-apt source tree, but can be + used for all Python code using python-apt. -- Julian Andres Klode Fri, 17 Apr 2009 17:48:27 +0200 diff --git a/utils/migrate-0.8.py b/utils/migrate-0.8.py new file mode 100755 index 00000000..b3f143b0 --- /dev/null +++ b/utils/migrate-0.8.py @@ -0,0 +1,194 @@ +#!/usr/bin/python2.6 +# +# migrate-0.8.py - Find use of deprecated methods/attributes in the code. +# +# Copyright (C) 2009 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +"""migrate-0.8.py - Find all occurences of funcs./attrs. deprecated in 0.8. + +Usage: python2.6 migrate-0.8.py [options] ... + +This reads the list of all functions and attributes available only in +COMPAT_0_7 builds and checks for occurences in the given Python modules. Has +to be run from the python-apt source code directory. + +Requires python2.6 to be installed. + +Parameters: + -h Display this help + -c Colorize the matching parts in the output. +""" +import _ast +import ast +import glob +import linecache +import os +import re +import sys +import types +from collections import defaultdict +from textwrap import fill + +color=False +if sys.argv[1] in ('-c', '--color', '--colour'): + color=True + del sys.argv[1] + +if '-h' in sys.argv or '--help' in sys.argv or not sys.argv[1:]: + print __doc__.strip() + sys.exit(0) + +if os.path.dirname(__file__).endswith('utils'): + sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) + + +def do_color(string, words): + """Colorize (red) the given words in the given string.""" + if not color: + return string + for word in words: + string = re.sub('([^_]*)(%s)([^_]*)' % word, "\\1\033[31m\033[1m" + + r"\2" + "\033[0m\\3", string) + return string + + +def find_deprecated_cpp(): + """Find all the deprecated functions and attributes.""" + is_open=False + all_old = set() + for fname in glob.glob('python/*.cc'): + lines = list(open(fname, 'r')) + while lines: + line = lines.pop(0) + while lines and not ('static PyMethodDef' in line or + 'static PyGetSetDef' in line): + line = lines.pop(0) + if not lines: + break + + while lines and not ';' in line: + while lines and not 'COMPAT_0_7' in line: + line = lines.pop(0) + if lines: + line = lines.pop(0) + while lines and not '#endif' in line: + all_old.add(line.split(",")[0].strip().strip('{"')) + line = lines.pop(0) + return all_old + + +def find_deprecated_py(): + """Same as find_deprecated_cpp(), but for apt and aptsources. + + We import apt_pkg, set _COMPAT_0_7 to 0, import apt and aptsources and + create a list of all attributes. + + No we remove the imported modules, reimport them (with _COMPAT_0_7=1), + and see which functions have been removed. + """ + + modules = ('apt', 'apt.package', 'apt.cdrom', 'apt.cache', 'apt.debfile', + 'apt.progress', 'aptsources.distinfo', 'aptsources.distro', + 'aptsources.sourceslist') + + import apt_pkg + apt_pkg._COMPAT_0_7 = 0 + + empty = set(sys.modules) + new, deprecated = set(), set() + + for mname in sorted(modules): + module = __import__(mname) + + for clsname in dir(module): + cls = getattr(module, clsname) + if not isinstance(cls, types.TypeType): + new.add(clsname) + continue + new.update(dir(cls)) + + for mname in sys.modules.keys(): + if not mname in empty: + del sys.modules[mname] + + apt_pkg._COMPAT_0_7 = 1 + + for mname in sorted(modules): + module = __import__(mname) + for clsname in dir(module): + cls = getattr(module, clsname) + if not isinstance(cls, types.TypeType): + deprecated.add(clsname) + continue + deprecated.update(dir(cls)) + + + for mname in sys.modules.keys(): + if not mname in empty: + del sys.modules[mname] + + return deprecated.difference(new) + + +def find_occurences(all_old, files): + """Find all ocurrences in the given Python files.""" + for fname in files: + if fname.endswith('setup3.py') or not fname.endswith('.py'): + continue + + words = defaultdict(lambda: set()) + for i in ast.walk(ast.parse(open(fname).read())): + + if isinstance(i, _ast.ImportFrom): + for alias in i.names: + if alias.name in all_old: + words[i.lineno].add(alias.name) + if isinstance(i, _ast.Name) and i.id in all_old: + words[i.lineno].add(i.id) + + if isinstance(i, _ast.Attribute) and i.attr in all_old: + words[i.lineno].add(i.attr) + + for lineno in sorted(words): + line = do_color(linecache.getline(fname, lineno).rstrip('\n'), + words[lineno]) + print '%s:%s:%s' % (fname, lineno, line) + +# Now, let's find them in the code. + +print __doc__.split("\n")[0] +print +if color: + print fill('Information: The color is not always correct, because we ' + 'simply highlight the matched words (like grep).', 79) + print + +all_old = find_deprecated_cpp() | find_deprecated_py() + + +files = set() +for path in sys.argv[1:]: + if not os.path.exists(path): + raise ValueError('Path does not exist: %s' % path) + if os.path.isfile(path): + files.add(path) + else: + for root, dirs, files_ in os.walk(path): + for fname in files_: + files.add(os.path.normpath(os.path.join(root, fname))) + +find_occurences(all_old, sorted(files)) -- cgit v1.2.3 From aa5b58b56b7e332d15e6ac9f3dfeffa60c2749a6 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 24 Apr 2009 18:43:52 +0200 Subject: * debian/control: Do not require python >= 2.5, mistake in previous commit. --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 374a177c..08ee329f 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: APT Development Team Uploaders: Michael Vogt , Julian Andres Klode Standards-Version: 3.8.1 -XS-Python-Version: >= 2.5 +XS-Python-Version: all Build-Depends: apt-utils, cdbs, debhelper (>= 5.0.37.1), -- cgit v1.2.3 From 7ba5f4686ddea5076f086d54e68dd407bff32147 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 24 Apr 2009 19:02:11 +0200 Subject: * debian/rules: Support multiple PY3K versions. Introduce PY3K_VERSIONS, a list of all py3k versions the package should be built for. The default is to build for the currently installed versions. Introduce 2TO3_VERSION to select a 2to3 version which will convert the python code to python 3. Points to the latest version by default. --- debian/rules | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'debian') diff --git a/debian/rules b/debian/rules index 5fc6e13b..7a6ff690 100755 --- a/debian/rules +++ b/debian/rules @@ -11,7 +11,9 @@ DEB_PYTHON_PACKAGES_EXCLUDE=python-apt-dbg include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/python-distutils.mk -PY3K = y +PY3K_VERSIONS := $(shell find /usr/bin/python3.? | sed s/.*python//) +2TO3_VERSION := $(lastword $(PY3K_VERSIONS)) + PKG=python-apt DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv @@ -21,17 +23,20 @@ DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us export CFLAGS+=-DCOMPAT_0_7 export DEBVER - -ifeq ($(PY3K),y) build/python-apt:: - python3.1 setup3.py build + set -e; for i in $(PY3K_VERSIONS); do \ + python$$i setup3.py build; \ + done install/python-apt:: - python3.1 ./setup3.py install --root $(CURDIR)/debian/python-apt \ - --install-layout=deb --no-compile + set -e; for i in $(PY3K_VERSIONS); do \ + python$$i ./setup3.py install --root $(CURDIR)/debian/python-apt \ + --install-layout=deb --no-compile; \ + done - find $(CURDIR)/debian/python-apt/usr/lib/python3.1/dist-packages/ -name '*.py' \ - | xargs 2to3-3.1 | patch -p0 +ifneq ($(PY3K_VERSIONS),) + find $(CURDIR)/debian/python-apt/usr/lib/python3*/dist-packages/ -name '*.py' \ + | xargs 2to3-$(2TO3_VERSION)| patch -p0 endif build/python-apt-dbg:: @@ -39,25 +44,29 @@ build/python-apt-dbg:: for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py build; \ done -ifeq ($(PY3K),y) - python3.1-dbg ./setup3.py build -endif + set -e; for i in $(PY3K_VERSIONS); do \ + python$$i-dbg setup3.py build; \ + done + install/python-apt-dbg:: for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py install --root $(CURDIR)/debian/python-apt-dbg \ --no-compile; \ done -ifeq ($(PY3K),y) - python3.1-dbg ./setup3.py install --root $(CURDIR)/debian/python-apt-dbg \ - --install-layout=deb --no-compile -endif + + set -e; for i in $(PY3K_VERSIONS); do \ + python$$i-dbg ./setup3.py install --root $(CURDIR)/debian/python-apt-dbg \ + --install-layout=deb --no-compile; \ + done + find debian/python-apt-dbg \ ! -type d ! -name '*_d.so' | xargs rm -f find debian/python-apt-dbg -depth -empty -exec rmdir {} \; binary-predeb/python-apt:: - ln -sf ../../../../javascript/jquery/jquery.js debian/python-apt/usr/share/doc/python-apt/html/_static/jquery.js + ln -sf ../../../../javascript/jquery/jquery.js \ + debian/python-apt/usr/share/doc/python-apt/html/_static/jquery.js binary-predeb/python-apt-dbg:: rm -rf debian/python-apt-dbg/usr/share/doc/python-apt-dbg -- cgit v1.2.3 From 7d6f85c475d5f50e0c54814cd8b644e38147b282 Mon Sep 17 00:00:00 2001 From: Stefano Zacchiroli Date: Mon, 18 May 2009 17:54:18 +0200 Subject: * debian/python-apt.doc-base: register the documentation with the doc-base system (Closes: #525134) --- debian/changelog | 5 +++++ debian/python-apt.doc-base | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 debian/python-apt.doc-base (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index f2d57afa..f2e03811 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,6 @@ python-apt (0.7.91) UNRELEASED; urgency=low + [ Julian Andres Klode ] * Rename all methods,functions,attributes to conform to PEP 8 (Closes: #481061) * Where possible, derive apt.package.Record from collections.Mapping. * ActionGroups can be used as a context manager for the 'with' statement. @@ -7,6 +8,10 @@ python-apt (0.7.91) UNRELEASED; urgency=low attributes,etc. Has to be run from the python-apt source tree, but can be used for all Python code using python-apt. + [ Stefano Zacchiroli ] + * debian/python-apt.doc-base: register the documentation with the + doc-base system (Closes: #525134) + -- Julian Andres Klode Fri, 17 Apr 2009 17:48:27 +0200 python-apt (0.7.90) experimental; urgency=low diff --git a/debian/python-apt.doc-base b/debian/python-apt.doc-base new file mode 100644 index 00000000..d25926b7 --- /dev/null +++ b/debian/python-apt.doc-base @@ -0,0 +1,11 @@ +Document: python-apt-api-reference +Title: Python APT: API reference manual +Abstract: API reference manual for Python bindings to libapt-pkg +Section: Programming/Python + +Format: HTML +Index: /usr/share/doc/python-apt/html/index.html +Files: /usr/share/doc/python-apt/html/* + +Format: Text +Files: /usr/share/doc/python-apt/text/* -- cgit v1.2.3 From 4ced65ec744e29019e7890eb6f505387940e74d5 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 5 Jun 2009 19:36:59 +0200 Subject: debian/control: Only recommend libjs-jquery (Closes: #527543). --- debian/changelog | 3 ++- debian/control | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index f2e03811..6150632c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,12 +7,13 @@ python-apt (0.7.91) UNRELEASED; urgency=low * utils/migrate-0.8.py: Helper to check Python code for deprecated functions, attributes,etc. Has to be run from the python-apt source tree, but can be used for all Python code using python-apt. + * debian/control: Only recommend libjs-jquery (Closes: #527543). [ Stefano Zacchiroli ] * debian/python-apt.doc-base: register the documentation with the doc-base system (Closes: #525134) - -- Julian Andres Klode Fri, 17 Apr 2009 17:48:27 +0200 + -- Julian Andres Klode Fri, 05 Jun 2009 19:36:45 +0200 python-apt (0.7.90) experimental; urgency=low diff --git a/debian/control b/debian/control index 08ee329f..25c58f15 100644 --- a/debian/control +++ b/debian/control @@ -23,9 +23,8 @@ Vcs-Browser: http://bzr.debian.org/loggerhead/apt/python-apt/debian-sid/changes Package: python-apt Architecture: any -Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, lsb-release, - libjs-jquery -Recommends: iso-codes +Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, lsb-release +Recommends: iso-codes, libjs-jquery Breaks: debdelta (<< 0.28~) Provides: ${python:Provides} Suggests: python-apt-dbg, python-gtk2, python-vte -- cgit v1.2.3 From 6c4e35354bba110758d9009e1555b2e13cd5ce4f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 5 Jun 2009 19:48:35 +0200 Subject: Set distribution to experimental. --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 61ec1527..55e68a52 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,7 @@ -python-apt (0.7.91) UNRELEASED; urgency=low +python-apt (0.7.91) experimental; urgency=low [ Julian Andres Klode ] - * Rename all methods,functions,attributes to conform to PEP 8 (Closes: #481061) + * Rename where needed according to PEP 8 conventions (Closes: #481061) * Where possible, derive apt.package.Record from collections.Mapping. * ActionGroups can be used as a context manager for the 'with' statement. * utils/migrate-0.8.py: Helper to check Python code for deprecated functions, -- cgit v1.2.3 From 33293ab8c53a9b1427012c297f288972e11ea3bb Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 8 Jun 2009 17:47:46 +0200 Subject: Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141) --- debian/changelog | 6 +++ python/apt_pkgmodule.cc | 2 + python/apt_pkgmodule.h | 7 +++ python/hashstring.cc | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ python/indexrecords.cc | 121 +++++++++++++++++++++++++++++++++++++++++ python/makefile | 2 +- 6 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 python/hashstring.cc create mode 100644 python/indexrecords.cc (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index ca215554..1a80d081 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +python-apt (0.7.92) experimental; urgency=low + + * Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141) + + -- Julian Andres Klode Mon, 08 Jun 2009 17:23:37 +0200 + python-apt (0.7.91) experimental; urgency=low [ Julian Andres Klode ] diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 4ad4e56c..085d12f4 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -603,6 +603,8 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"SourceRecords",&PkgSrcRecordsType); /* ========================= sourcelist.cc ========================= */ ADDTYPE(Module,"SourceList",&PkgSourceListType); + ADDTYPE(Module,"IndexRecords",&PyIndexRecords_Type); + ADDTYPE(Module,"HashString",&PyHashString_Type); // Tag file constants PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", CharCharToList(TFRewritePackageOrder)); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index f7ef63c2..043e29cc 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -11,6 +11,7 @@ #define APT_PKGMODULE_H #include +#include // Configuration Stuff #define Configuration_Check(op) ((op)->ob_type == &ConfigurationType || \ @@ -106,5 +107,11 @@ extern PyTypeObject PackageIndexFileType; // metaIndex extern PyTypeObject MetaIndexType; +// HashString +PyObject *PyHashString_FromCpp(HashString *obj); +extern PyTypeObject PyHashString_Type; + +// IndexRecord +extern PyTypeObject PyIndexRecords_Type; #endif diff --git a/python/hashstring.cc b/python/hashstring.cc new file mode 100644 index 00000000..02a80210 --- /dev/null +++ b/python/hashstring.cc @@ -0,0 +1,140 @@ +/* hashstring.cc - Wrapper around HashString + * + * Copyright 2009 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 "generic.h" +#include "apt_pkgmodule.h" +#include + +static PyObject *HashString_NEW(PyTypeObject *type,PyObject *Args, + PyObject *kwds) +{ + const char *Hash; + const char *Type; + char *kwlist[] = {"type", "hash", NULL}; + if (PyArg_ParseTupleAndKeywords(Args, kwds, "s|s", kwlist, &Type, + &Hash) == 0) + return 0; + CppPyObject *PyObj = CppPyObject_NEW(type); + if (Hash) + PyObj->Object = new HashString(Type,Hash); + else // Type is the combined form now (i.e. type:hash) + PyObj->Object = new HashString(Type); + return PyObj; +} + +PyObject *PyHashString_FromCpp(HashString *obj) +{ + return CppPyObject_NEW(&PyHashString_Type, obj); +} + +static PyObject *HashString_Repr(PyObject *self) +{ + HashString *hash = GetCpp(self); + char repr[100]; + sprintf(repr, "<%s: \"%s\">", self->ob_type->tp_name, hash->toStr().c_str()); + return PyString_FromString(repr); +} + +static PyObject *HashString_ToStr(PyObject *self) +{ + HashString *hash = GetCpp(self); + return CppPyString(hash->toStr()); +} + +static PyObject *HashString_HashType(PyObject *self) +{ + HashString *hash = GetCpp(self); + return CppPyString(hash->HashType()); +} + +static const char *HashString_VerifyFile_doc = + "verify_file(filename: str) --> bool\n\n" + "Verify that the file indicated by filename matches the hash."; + +static PyObject *HashString_VerifyFile(PyObject *self,PyObject *args) +{ + HashString *hash = GetCpp(self); + char *filename; + if (PyArg_ParseTuple(args, "s", &filename) == 0) + return 0; + return PyBool_FromLong(hash->VerifyFile(filename)); +} + +static PyMethodDef HashString_Methods[] = { + {"to_str",(PyCFunction)HashString_ToStr,METH_NOARGS, + "to_str() --> str\n\nReturn a string, consisting of type:hash"}, + {"verify_file",HashString_VerifyFile,METH_VARARGS, + HashString_VerifyFile_doc}, + {"hash_type",(PyCFunction)HashString_HashType,METH_NOARGS, + "hash_type() --> str\n\nReturn the type of hash (MD5Sum,SHA1,SHA256)"}, + {} +}; + +static const char *HashString_doc = + "HashString(type, hash) OR HashString('type:hash')\n\n" + "Create a new HashString object. The first form allows you to specify\n" + "a type and a hash, and the second form a single string where type and\n" + "hash are seperated by a colon, e.g.::\n\n" + " HashString('MD5Sum', '6cc1b6e6655e3555ac47e5b5fe26d04e')\n\n" + "Valid options for 'type' are: MD5Sum, SHA1, SHA256."; +PyTypeObject PyHashString_Type = { + PyObject_HEAD_INIT(&PyType_Type) +#if PY_MAJOR_VERSION < 3 + 0, // ob_size +#endif + "apt_pkg.HashString", // 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 + HashString_Repr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + HashString_ToStr, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + HashString_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + HashString_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 + HashString_NEW, // tp_new +}; diff --git a/python/indexrecords.cc b/python/indexrecords.cc new file mode 100644 index 00000000..e6099a69 --- /dev/null +++ b/python/indexrecords.cc @@ -0,0 +1,121 @@ +/* + * indexrecords.cc - Wrapper around indexRecords + * + * Copyright 2009 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 + +static PyObject *IndexRecords_NEW(PyTypeObject *type,PyObject *Args, + PyObject *kwds) +{ + char * kwlist[] = {NULL}; + if (PyArg_ParseTupleAndKeywords(Args, kwds, "", kwlist) == 0) + return 0; + indexRecords *records = new indexRecords(); + CppPyObject *New = CppPyObject_NEW(type, + records); + return New; +} + +static PyObject *IndexRecords_Load(PyObject *self,PyObject *args) +{ + const char *filename; + if (PyArg_ParseTuple(args, "s", &filename) == 0) + return 0; + indexRecords *records = GetCpp(self); + return HandleErrors(Py_BuildValue("i", records->Load(filename))); +} + +static const char *IndexRecords_Lookup_doc = "lookup(metakey)\n\n" + "Lookup the filename given by metakey, return a tuple (size,hash).\n" + "The hash part is a HashString() object."; +static PyObject *IndexRecords_Lookup(PyObject *self,PyObject *args) +{ + const char *keyname; + if (PyArg_ParseTuple(args, "s", &keyname) == 0) + return 0; + indexRecords *records = GetCpp(self); + const indexRecords::checkSum *result = records->Lookup(keyname); + return Py_BuildValue("(iO)",result->Size, + PyHashString_FromCpp((HashString*)&result->Hash)); +} + +static PyObject *IndexRecords_GetDist(PyObject *self) +{ + indexRecords *records = GetCpp(self); + return HandleErrors(PyString_FromString(records->GetDist().c_str())); +} + +static PyMethodDef IndexRecords_Methods[] = { + {"load",IndexRecords_Load,METH_VARARGS, + "load(filename: str)\n\nLoad the file given by filename."}, + {"get_dist",(PyCFunction)IndexRecords_GetDist,METH_NOARGS, + "get_dist() -> str\n\nReturn a distribution set in the release file."}, + {"lookup",IndexRecords_Lookup,METH_VARARGS,IndexRecords_Lookup_doc}, + {} +}; + +static char *IndexRecords_doc = "IndexRecords()\n\n" + "Representation of a release file."; +PyTypeObject PyIndexRecords_Type = { + PyObject_HEAD_INIT(&PyType_Type) +#if PY_MAJOR_VERSION < 3 + 0, // ob_size +#endif + "apt_pkg.IndexRecords", // 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 + 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 + IndexRecords_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + IndexRecords_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 + IndexRecords_NEW, // tp_new +}; diff --git a/python/makefile b/python/makefile index 3e6458f4..f4d559ce 100644 --- a/python/makefile +++ b/python/makefile @@ -12,7 +12,7 @@ LIB_MAKES = apt-pkg/makefile APT_PKG_SRC = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \ cache.cc pkgrecords.cc pkgsrcrecords.cc sourcelist.cc \ depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \ - indexfile.cc metaindex.cc + indexfile.cc metaindex.cc hashstring.cc indexrecords.cc SOURCE := $(APT_PKG_SRC) include $(PYTHON_H) progress.h -- cgit v1.2.3 From f652213b76f72382bab21e730bf0ccc4419a1267 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 9 Jun 2009 18:10:19 +0200 Subject: Allow types providing __new__() to be subclassed. --- debian/changelog | 3 ++- python/acquire.cc | 6 ++++-- python/cache.cc | 3 ++- python/cdrom.cc | 3 ++- python/configuration.cc | 3 ++- python/depcache.cc | 9 ++++++--- python/hashstring.cc | 3 ++- python/indexrecords.cc | 3 ++- python/pkgmanager.cc | 3 ++- python/pkgrecords.cc | 3 ++- python/pkgsrcrecords.cc | 3 ++- python/sourcelist.cc | 3 ++- python/tag.cc | 6 ++++-- 13 files changed, 34 insertions(+), 17 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 1a80d081..818bf630 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ python-apt (0.7.92) experimental; urgency=low * Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141) + * Allow types providing __new__() to be subclassed. - -- Julian Andres Klode Mon, 08 Jun 2009 17:23:37 +0200 + -- Julian Andres Klode Tue, 09 Jun 2009 18:09:53 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/acquire.cc b/python/acquire.cc index 05bffc65..702d48ce 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -276,7 +276,8 @@ PyTypeObject PkgAcquireType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), doc_PkgAcquire, // tp_doc 0, // tp_traverse 0, // tp_clear @@ -366,7 +367,8 @@ PyTypeObject PkgAcquireFileType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), doc_PkgAcquireFile, // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/cache.cc b/python/cache.cc index c988145f..14484104 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -331,7 +331,8 @@ PyTypeObject PkgCacheType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT , // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), doc_PkgCache, // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/cdrom.cc b/python/cdrom.cc index 3e63a89c..e98947d1 100644 --- a/python/cdrom.cc +++ b/python/cdrom.cc @@ -108,7 +108,8 @@ PyTypeObject PkgCdromType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), "Cdrom Object", // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/configuration.cc b/python/configuration.cc index 3c6ea88c..365a35fd 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -526,7 +526,8 @@ PyTypeObject ConfigurationType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), "Configuration Object", // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/depcache.cc b/python/depcache.cc index a69e0723..f1c34fef 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -675,7 +675,8 @@ PyTypeObject PkgDepCacheType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), doc_PkgDepCache, // tp_doc 0, // tp_traverse 0, // tp_clear @@ -858,7 +859,8 @@ PyTypeObject PkgProblemResolverType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), "ProblemResolver Object", // tp_doc 0, // tp_traverse 0, // tp_clear @@ -975,7 +977,8 @@ PyTypeObject PkgActionGroupType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), doc_PkgActionGroup, // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/hashstring.cc b/python/hashstring.cc index 71ae5bf4..58bcca9e 100644 --- a/python/hashstring.cc +++ b/python/hashstring.cc @@ -118,7 +118,8 @@ PyTypeObject PyHashString_Type = { 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), HashString_doc, // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/indexrecords.cc b/python/indexrecords.cc index 35e41c59..61ff07fc 100644 --- a/python/indexrecords.cc +++ b/python/indexrecords.cc @@ -104,7 +104,8 @@ PyTypeObject PyIndexRecords_Type = { 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), IndexRecords_doc, // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index 7752ce5b..f47e77ad 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -153,7 +153,8 @@ PyTypeObject PkgManagerType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), "PackageManager Object", // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc index 6022097a..8beefffd 100644 --- a/python/pkgrecords.cc +++ b/python/pkgrecords.cc @@ -186,7 +186,8 @@ PyTypeObject PkgRecordsType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), "Records Object", // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc index 50445432..e6b78a83 100644 --- a/python/pkgsrcrecords.cc +++ b/python/pkgsrcrecords.cc @@ -228,7 +228,8 @@ PyTypeObject PkgSrcRecordsType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), "SourceRecords Object", // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/sourcelist.cc b/python/sourcelist.cc index 1c05d83e..5e5838d8 100644 --- a/python/sourcelist.cc +++ b/python/sourcelist.cc @@ -138,7 +138,8 @@ PyTypeObject PkgSourceListType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), "pkgSourceList Object", // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/python/tag.cc b/python/tag.cc index 31491c90..7e7eb21c 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -434,7 +434,8 @@ PyTypeObject TagSecType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), doc_TagSec, // tp_doc 0, // tp_traverse 0, // tp_clear @@ -521,7 +522,8 @@ PyTypeObject TagFileType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), doc_TagFile, // tp_doc 0, // tp_traverse 0, // tp_clear -- cgit v1.2.3 From a307f6c405d55895690e16d55de36549f5b05d8b Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 9 Jun 2009 20:44:58 +0200 Subject: Add apt_pkg.Policy class (Closes: #382725) --- debian/changelog | 3 +- python/apt_pkgmodule.cc | 1 + python/apt_pkgmodule.h | 3 + python/makefile | 2 +- python/policy.cc | 189 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 python/policy.cc (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 818bf630..3e85c5be 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,10 @@ python-apt (0.7.92) experimental; urgency=low * Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141) + * Add apt_pkg.Policy class (Closes: #382725) * Allow types providing __new__() to be subclassed. - -- Julian Andres Klode Tue, 09 Jun 2009 18:09:53 +0200 + -- Julian Andres Klode Tue, 09 Jun 2009 20:39:39 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 95b72de4..3d76894d 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -606,6 +606,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"SourceList",&PkgSourceListType); ADDTYPE(Module,"IndexRecords",&PyIndexRecords_Type); ADDTYPE(Module,"HashString",&PyHashString_Type); + ADDTYPE(Module,"Policy",&PyPolicy_Type); // Tag file constants PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", CharCharToList(TFRewritePackageOrder)); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 043e29cc..21355072 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -114,4 +114,7 @@ extern PyTypeObject PyHashString_Type; // IndexRecord extern PyTypeObject PyIndexRecords_Type; +// Policy +extern PyTypeObject PyPolicy_Type; + #endif diff --git a/python/makefile b/python/makefile index f4d559ce..6799d749 100644 --- a/python/makefile +++ b/python/makefile @@ -12,7 +12,7 @@ LIB_MAKES = apt-pkg/makefile APT_PKG_SRC = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \ cache.cc pkgrecords.cc pkgsrcrecords.cc sourcelist.cc \ depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \ - indexfile.cc metaindex.cc hashstring.cc indexrecords.cc + indexfile.cc metaindex.cc hashstring.cc indexrecords.cc policy.cc SOURCE := $(APT_PKG_SRC) include $(PYTHON_H) progress.h diff --git a/python/policy.cc b/python/policy.cc new file mode 100644 index 00000000..89604e9a --- /dev/null +++ b/python/policy.cc @@ -0,0 +1,189 @@ +/* + * policy.cc - Wrapper around pkgPolicy + * + * Copyright 2009 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 + +static PyObject *Policy_NEW(PyTypeObject *type,PyObject *Args, + PyObject *kwds) { + PyObject *cache; + char *kwlist[] = {"cache", NULL}; + if (PyArg_ParseTupleAndKeywords(Args, kwds, "O", kwlist, &cache) == 0) + return 0; + if (!PyObject_TypeCheck(cache, &PkgCacheType)) { + PyErr_SetString(PyExc_TypeError,"`cache` must be a apt_pkg.Cache()."); + return 0; + } + pkgPolicy *policy = new pkgPolicy(GetCpp(cache)); + return CppOwnedPyObject_NEW(cache,&PyPolicy_Type,policy); +} + +static char *Policy_GetPriority_doc = "get_priority(package: apt_pkg.Package)" + " -> int\n\n" + "Return the priority of the package."; + +PyObject *Policy_GetPriority(PyObject *self, PyObject *arg) { + pkgPolicy *policy = GetCpp(self); + if (PyObject_TypeCheck(arg, &PackageType)) { + pkgCache::PkgIterator pkg = GetCpp(arg); + return Py_BuildValue("i", policy->GetPriority(pkg)); + } else { + PyErr_SetString(PyExc_TypeError,"Argument must be of Package()."); + return 0; + } +} + +static char *Policy_GetCandidateVer_doc = "get_match(package: apt_pkg.Package)" + " -> apt_pkg.Version\n\n" + "Get the best package for the job."; + +PyObject *Policy_GetCandidateVer(PyObject *self, PyObject *arg) { + if (PyObject_TypeCheck(arg, &PackageType)) { + pkgPolicy *policy = GetCpp(self); + pkgCache::PkgIterator pkg = GetCpp(arg); + pkgCache::VerIterator ver = policy->GetCandidateVer(pkg); + return CppOwnedPyObject_NEW(arg,&VersionType, + ver); + } else { + PyErr_SetString(PyExc_TypeError,"Argument must be of Package()."); + return 0; + } +} + +static char *Policy_GetMatch_doc = "get_match(package: apt_pkg.Package) -> " + "apt_pkg.Version\n\n" + "Return a matching version for the given package."; + +static PyObject *Policy_GetMatch(PyObject *self, PyObject *arg) { + if (PyObject_TypeCheck(arg, &PackageType) == 0) { + PyErr_SetString(PyExc_TypeError,"Argument must be of Package()."); + return 0; + } + pkgPolicy *policy = GetCpp(self); + pkgCache::PkgIterator pkg = GetCpp(arg); + pkgCache::VerIterator ver = policy->GetMatch(pkg); + return CppOwnedPyObject_NEW(arg,&VersionType,ver); +} + +static char *Policy_ReadPinFile_doc = "read_pinfile(filename: str) -> bool\n\n" + "Read the pin file given by filename (e.g. '/etc/apt/preferences') and\n" + "add it to the policy."; + +static PyObject *Policy_ReadPinFile(PyObject *self, PyObject *arg) { + if (!PyString_Check(arg)) + return 0; + pkgPolicy *policy = GetCpp(self); + + return PyBool_FromLong(ReadPinFile(*policy, PyString_AsString(arg))); +} + +static char *Policy_CreatePin_doc = "create_pin(type: str, pkg: str, " + "data: str, priority: int)\n\n" + "Create a pin for the policy. The parameter 'type' refers to one of the\n" + "following strings: 'Version', 'Release', 'Origin'. The argument 'pkg'\n" + "is the name of the package, the parameter 'data' refers to the value\n" + "e.g. unstable for type='Release' and the other possible options. \n" + "The parameter 'priority' gives the priority of the pin."; + +static PyObject *Policy_CreatePin(PyObject *self, PyObject *args) { + pkgVersionMatch::MatchType match_type; + const char *type, *pkg, *data; + signed short priority; + if (PyArg_ParseTuple(args, "sssh", &type, &pkg, &data, &priority) == 0) + return 0; + pkgPolicy *policy = GetCpp(self); + if (type == "Version" || type == "version") + match_type = pkgVersionMatch::Version; + if (type == "Release" || type == "release") + match_type = pkgVersionMatch::Release; + if (type == "Origin" || type == "origin") + match_type = pkgVersionMatch::Origin; + else + match_type = pkgVersionMatch::None; + policy->CreatePin(match_type,pkg,data,priority); + HandleErrors(); + Py_RETURN_NONE; +} + +static PyMethodDef Policy_Methods[] = { + {"get_priority",(PyCFunction)Policy_GetPriority,METH_O, + Policy_GetPriority_doc}, + {"get_candidate_ver",(PyCFunction)Policy_GetCandidateVer,METH_O, + Policy_GetCandidateVer_doc}, + {"read_pinfile",(PyCFunction)Policy_ReadPinFile,METH_O, + Policy_ReadPinFile_doc}, + {"create_pin",Policy_CreatePin,METH_VARARGS,Policy_CreatePin_doc}, + {"get_match",(PyCFunction)Policy_GetMatch,METH_O, Policy_GetMatch_doc}, + {} +}; + +static char *Policy_doc = "Policy(cache)\n\n" + "Representation of the policy of the Cache object given by cache. This\n" + "provides a superset of policy-related functionality compared to the\n" + "DepCache class. The DepCache can be used for most purposes, but there\n" + "may be some cases where a special policy class is needed."; + +PyTypeObject PyPolicy_Type = { + PyObject_HEAD_INIT(&PyType_Type) +#if PY_MAJOR_VERSION < 3 + 0, // ob_size +#endif + "apt_pkg.Policy", // tp_name + sizeof(CppOwnedPyObject),// tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDealloc, // 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), + Policy_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + Policy_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 + Policy_NEW, // tp_new +}; -- cgit v1.2.3 From 395b33f9f8e93223f933c625bacbf1e2d23c6673 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 12 Jun 2009 18:56:23 +0200 Subject: Bugfix: Delete pointers correctly, fixing memory leaks. (LP: #370149) We previously called the destructor of the pointer. This resulted in no object using pointers being deallocated. This patch introduces CppDeallocPtr() and CppOwnedDeallocPtr() which do the same as the other CppDealloc() and CppOwnedDealloc(), but use 'delete' on the pointer instead of the deconstructor. Furthermore, this patch also changes AcquireFile to be a CppOwnedPyObject, owned by the Acquire object. Without this change, deleting the Acquire object would cause a crash when AcquireFile is deallocated. --- debian/changelog | 5 +++-- python/acquire.cc | 8 ++++---- python/cache.cc | 4 ++-- python/depcache.cc | 6 +++--- python/generic.h | 19 +++++++++++++++++++ python/hashstring.cc | 2 +- python/indexfile.cc | 2 +- python/indexrecords.cc | 2 +- python/metaindex.cc | 2 +- python/pkgmanager.cc | 2 +- python/policy.cc | 2 +- python/sourcelist.cc | 2 +- 12 files changed, 38 insertions(+), 18 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 3e85c5be..9f9838c3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,11 @@ -python-apt (0.7.92) experimental; urgency=low +python-apt (0.7.92) UNRELEASED; urgency=low * Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141) * Add apt_pkg.Policy class (Closes: #382725) * Allow types providing __new__() to be subclassed. + * Bugfix: Delete pointers correctly, fixing memory leaks. (LP: #370149) - -- Julian Andres Klode Tue, 09 Jun 2009 20:39:39 +0200 + -- Julian Andres Klode Fri, 12 Jun 2009 18:42:02 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/acquire.cc b/python/acquire.cc index 702d48ce..6b091479 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -261,7 +261,7 @@ PyTypeObject PkgAcquireType = sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc, // tp_dealloc + CppDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -329,7 +329,7 @@ static PyObject *PkgAcquireFileNew(PyTypeObject *type, PyObject *Args, PyObject shortDescr, destDir, destFile); // short-desc - CppPyObject *AcqFileObj = CppPyObject_NEW(type); + CppOwnedPyObject *AcqFileObj = CppOwnedPyObject_NEW(pyfetcher, type); AcqFileObj->Object = af; return AcqFileObj; @@ -349,10 +349,10 @@ PyTypeObject PkgAcquireFileType = 0, // ob_size #endif "apt_pkg.AcquireFile", // tp_name - sizeof(CppPyObject),// tp_basicsize + sizeof(CppOwnedPyObject),// tp_basicsize 0, // tp_itemsize // Methods - CppDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/cache.cc b/python/cache.cc index 14484104..22ed9ecc 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -247,7 +247,7 @@ void PkgCacheFileDealloc(PyObject *Self) PyObject *CacheFilePy = GetOwner(Self); pkgCacheFile *CacheF = GetCpp(CacheFilePy); CacheF->Close(); - CppOwnedDealloc(Self); + CppOwnedDeallocPtr(Self); } static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) @@ -365,7 +365,7 @@ PyTypeObject PkgCacheFileType = sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/depcache.cc b/python/depcache.cc index f1c34fef..9bbda527 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -660,7 +660,7 @@ PyTypeObject PkgDepCacheType = sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -844,7 +844,7 @@ PyTypeObject PkgProblemResolverType = sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + CppOwnedDeallocPtr,// tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -962,7 +962,7 @@ PyTypeObject PkgActionGroupType = sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/generic.h b/python/generic.h index df4d8755..b7b958f5 100644 --- a/python/generic.h +++ b/python/generic.h @@ -153,6 +153,25 @@ void CppOwnedDealloc(PyObject *iObj) iObj->ob_type->tp_free(iObj); } +// Pointer deallocation +// Generic Dealloc type functions +template +void CppDeallocPtr(PyObject *Obj) +{ + delete GetCpp(Obj); + Obj->ob_type->tp_free(Obj); +} + +template +void CppOwnedDeallocPtr(PyObject *iObj) +{ + CppOwnedPyObject *Obj = (CppOwnedPyObject *)iObj; + delete Obj->Object; + if (Obj->Owner != 0) + Py_DECREF(Obj->Owner); + iObj->ob_type->tp_free(iObj); +} + inline PyObject *CppPyString(std::string Str) { return PyString_FromStringAndSize(Str.c_str(),Str.length()); diff --git a/python/hashstring.cc b/python/hashstring.cc index 58bcca9e..23212a4b 100644 --- a/python/hashstring.cc +++ b/python/hashstring.cc @@ -103,7 +103,7 @@ PyTypeObject PyHashString_Type = { sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc, // tp_dealloc + CppDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/indexfile.cc b/python/indexfile.cc index 795931fb..78a4f513 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -99,7 +99,7 @@ PyTypeObject PackageIndexFileType = sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/indexrecords.cc b/python/indexrecords.cc index 61ff07fc..fcb2b85d 100644 --- a/python/indexrecords.cc +++ b/python/indexrecords.cc @@ -89,7 +89,7 @@ PyTypeObject PyIndexRecords_Type = { sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc, // tp_dealloc + CppDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/metaindex.cc b/python/metaindex.cc index b451f0b5..b5d194b4 100644 --- a/python/metaindex.cc +++ b/python/metaindex.cc @@ -80,7 +80,7 @@ PyTypeObject MetaIndexType = sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index f47e77ad..0fd2cd92 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -138,7 +138,7 @@ PyTypeObject PkgManagerType = sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc, // tp_dealloc + CppDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/policy.cc b/python/policy.cc index 89604e9a..992a1192 100644 --- a/python/policy.cc +++ b/python/policy.cc @@ -151,7 +151,7 @@ PyTypeObject PyPolicy_Type = { sizeof(CppOwnedPyObject),// tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/sourcelist.cc b/python/sourcelist.cc index 5e5838d8..e53fccd3 100644 --- a/python/sourcelist.cc +++ b/python/sourcelist.cc @@ -123,7 +123,7 @@ PyTypeObject PkgSourceListType = sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc, // tp_dealloc + CppDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr -- cgit v1.2.3 From 986993847b3d833f9ac0926c64f00fa03b895832 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 14 Jun 2009 16:47:05 +0200 Subject: apt/package.py: Return VersionList objects in Package.versions. VersionList objects provide the same features as sequences (they are even derived from collections.Sequence in Python 2.6 and newer), but also provide a mapping like interface. They are also more efficient than lists because Version objects are only created when they are accessed. --- apt/package.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++------ debian/changelog | 4 ++- 2 files changed, 87 insertions(+), 10 deletions(-) (limited to 'debian') diff --git a/apt/package.py b/apt/package.py index a0727429..0a80215e 100644 --- a/apt/package.py +++ b/apt/package.py @@ -29,10 +29,10 @@ import subprocess import urllib2 import warnings try: - from collections import Mapping + from collections import Mapping, Sequence except ImportError: # (for Python < 2.6) pylint: disable-msg=C0103 - Mapping = object + Sequence = Mapping = object import apt_pkg import apt.progress @@ -206,7 +206,10 @@ class Version(object): self._cand = cand def __eq__(self, other): - return self._cand.id == other._cand.id + try: + return self._cand.id == other._cand.id + except: + return apt_pkg.version_compare(self.version, other) == 0 def __gt__(self, other): return apt_pkg.version_compare(self.version, other.version) > 0 @@ -515,6 +518,81 @@ class Version(object): return os.path.abspath(dsc) +class VersionList(Sequence): + """Provide a mapping & sequence interface to all versions of a package. + + This class can be used like a dictionary, where version strings are the + keys. It can also be used as a sequence, where integers are the keys. + + You can also convert this to a dictionary or a list, using the usual way + of dict(version_list) or list(version_list). This is useful if you need + to access the version objects multiple times, because they do not have to + be recreated this way. + + Examples ('package.versions' being a version list): + '0.7.92' in package.versions # Check whether 0.7.92 is a valid version. + package.versions[0] # Return first version or raise IndexError + package.versions[0:2] # Return a new VersionList for objects 0-2 + package.versions['0.7.92'] # Return version 0.7.92 or raise KeyError + package.versions.keys() # All keys, as strings. + max(package.versions) + """ + + def __init__(self, package, slice=None): + self._package = package # apt.package.Package() + self._versions = package._pkg.version_list # [apt_pkg.Version(), ...] + if slice: + self._versions = self._versions[slice] + + def __getitem__(self, item): + if isinstance(item, slice): + return self.__class__(self._package, item) + try: + # Sequence interface, item is an integer + return Version(self._package, self._versions[item]) + except TypeError: + # Dictionary interface item is a string. + for ver in self._versions: + if ver.ver_str == item: + return Version(self._package, ver) + raise KeyError("Version: %r not found." % (item)) + + def __repr__(self): + return '' % self.keys() + + def __iter__(self): + """Return an iterator over all value objects.""" + return (Version(self._package, ver) for ver in self._versions) + + def __contains__(self, item): + if isinstance(item, Version): # Sequence interface + item = item.version + # Dictionary interface. + for ver in self._versions: + if ver.ver_str == item: + return True + return False + + def __eq__(self, other): + return list(self) == list(other) + + def __len__(self): + return len(self._versions) + + # Mapping interface + + def keys(self): + """Return a list of all versions, as strings.""" + return [ver.ver_str for ver in self._versions] + + def get(self, key, default=None): + """Return the key or the default.""" + try: + return self[key] + except LookupError: + return default + + class Package(object): """Representation of a package in a cache. @@ -988,18 +1066,15 @@ class Package(object): @property def versions(self): - """Return a list of versions. + """Return a VersionList() object for all available versions. .. versionadded:: 0.7.9 """ - return [Version(self, ver) for ver in self._pkg.version_list] + return VersionList(self) def get_version(self, version): """Get the Version instance matching the given version string.""" - for ver in self.versions: - if ver.version == version: - return ver - return None + return self.versions[version] # depcache actions diff --git a/debian/changelog b/debian/changelog index 7e79e89c..648b008d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,12 +5,14 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Add apt_pkg.Policy class (Closes: #382725) * Allow types providing __new__() to be subclassed. * Bugfix: Delete pointers correctly, fixing memory leaks. (LP: #370149) + * apt/package.py: Return VersionList objects in Package.versions, which + are sequences and also provide features of mappings. (small API BREAK) [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message (Closes: #532660) - -- Julian Andres Klode Fri, 12 Jun 2009 18:42:02 +0200 + -- Julian Andres Klode Sun, 14 Jun 2009 16:23:39 +0200 python-apt (0.7.91) experimental; urgency=low -- cgit v1.2.3 From dc759b837ad5d7790fd54f081c1b95ffe76b926c Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 15 Jun 2009 14:47:15 +0200 Subject: apt/progress/__init__.py: Check for EINTR in select (Closes: #499296) --- apt/progress/__init__.py | 8 +++++++- debian/changelog | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'debian') diff --git a/apt/progress/__init__.py b/apt/progress/__init__.py index a6287dc4..3c5d4588 100644 --- a/apt/progress/__init__.py +++ b/apt/progress/__init__.py @@ -116,6 +116,7 @@ class FetchProgress(object): This happens eg. when the downloads fails or is completed. """ + def update_status_full(self, uri, descr, short_descr, status, file_size, partial_size): """Called when the status of an item changes. @@ -314,7 +315,12 @@ class InstallProgress(DumbInstallProgress): def wait_child(self): """Wait for child progress to exit.""" while True: - select.select([self.statusfd], [], [], self.select_timeout) + try: + select.select([self.statusfd], [], [], self.select_timeout) + except select.error, e: + if e[0] != errno.EINTR: + raise + self.update_interface() (pid, res) = os.waitpid(self.child_pid, os.WNOHANG) if pid == self.child_pid: diff --git a/debian/changelog b/debian/changelog index 6ad40154..55d3a834 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Bugfix: Delete pointers correctly, fixing memory leaks. (LP: #370149) * apt/package.py: Return VersionList objects in Package.versions, which are sequences and also provide features of mappings. (small API BREAK) + * apt/progress/__init__.py: Check for EINTR in select (Closes: #499296) [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -22,7 +23,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Sun, 14 Jun 2009 16:23:39 +0200 + -- Julian Andres Klode Mon, 15 Jun 2009 14:45:06 +0200 python-apt (0.7.91) experimental; urgency=low -- cgit v1.2.3 From 7618780d7e0550897f87eecc4ab52d75b9c0ec39 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 15 Jun 2009 14:58:41 +0200 Subject: Add support for Enhances as a dependency type (Closes: #416247) --- debian/changelog | 1 + python/cache.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 55d3a834..9809d423 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * apt/package.py: Return VersionList objects in Package.versions, which are sequences and also provide features of mappings. (small API BREAK) * apt/progress/__init__.py: Check for EINTR in select (Closes: #499296) + * Add support for Enhances as a dependency type (Closes: #416247) [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/python/cache.cc b/python/cache.cc index 80a7a8a5..7e75ccab 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -711,7 +711,7 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, { "", "Depends","PreDepends","Suggests", "Recommends","Conflicts","Replaces", - "Obsoletes", "Breaks" + "Obsoletes", "Breaks", "Enhances" }; PyObject *Dep = PyString_FromString(Types[Start->Type]); LastDepType = Start->Type; -- cgit v1.2.3 From 56ce90ed8cc9ce939dd7904c9b07478b0c3b2071 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 15 Jun 2009 15:14:30 +0200 Subject: apt/cache.py: Provide broken_count, delete_count, install_count, keep_count properties (Closes: #532338) --- apt/cache.py | 20 ++++++++++++++++++++ debian/changelog | 2 ++ 2 files changed, 22 insertions(+) (limited to 'debian') diff --git a/apt/cache.py b/apt/cache.py index 16dfc011..949de6cc 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -368,6 +368,26 @@ class Cache(object): """ return apt_pkg.ActionGroup(self._depcache) + @property + def broken_count(self): + """Return the number of packages with broken dependencies.""" + return self._depcache.broken_count + + @property + def delete_count(self): + """Return the number of packages marked for deletion.""" + return self._depcache.del_count + + @property + def install_count(self): + """Return the number of packages marked for installation.""" + return self._depcache.inst_count + + @property + def keep_count(self): + """Return the number of packages marked as keep.""" + return self._depcache.keep_count + if apt_pkg._COMPAT_0_7: _runCallbacks = function_deprecated_by(_run_callbacks) getChanges = function_deprecated_by(get_changes) diff --git a/debian/changelog b/debian/changelog index 9809d423..97b49021 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low are sequences and also provide features of mappings. (small API BREAK) * apt/progress/__init__.py: Check for EINTR in select (Closes: #499296) * Add support for Enhances as a dependency type (Closes: #416247) + * apt/cache.py: Provide broken_count, delete_count, install_count, keep_count + properties (Closes: #532338) [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message -- cgit v1.2.3 From 6842933fb0b51aaa6fdc66e17b4645312876d0c9 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 21 Jun 2009 20:46:24 +0200 Subject: apt/cache.py: Correctly handle rootdir on second and later invocations of open() (LP: #320665). --- apt/cache.py | 4 ++++ debian/changelog | 2 ++ 2 files changed, 6 insertions(+) (limited to 'debian') diff --git a/apt/cache.py b/apt/cache.py index 737061ad..414bd982 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -80,6 +80,10 @@ class Cache(object): if progress is None: progress = apt.progress.OpProgress() self._run_callbacks("cache_pre_open") + + # Make changes to Dir::State::Status work again, by reinitialising + # the system. + apt_pkg.init_system() self._cache = apt_pkg.Cache(progress) self._depcache = apt_pkg.DepCache(self._cache) self._records = apt_pkg.PackageRecords(self._cache) diff --git a/debian/changelog b/debian/changelog index 97b49021..4fb6b0de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Add support for Enhances as a dependency type (Closes: #416247) * apt/cache.py: Provide broken_count, delete_count, install_count, keep_count properties (Closes: #532338) + * apt/cache.py: Correctly handle rootdir on second and later invocations of + open() (LP: #320665). [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message -- cgit v1.2.3 From b426f959e7e515d5f267558b6ae51ed9ae03fb9d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 22 Jun 2009 14:54:31 +0200 Subject: Add apt_pkg.DepCache.mark_auto() and apt.Package.mark_auto() methods to mark a package as automatically installed. --- apt/package.py | 13 +++++++++++++ debian/changelog | 4 +++- python/depcache.cc | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/apt/package.py b/apt/package.py index cb99fe6a..39a73c07 100644 --- a/apt/package.py +++ b/apt/package.py @@ -846,6 +846,10 @@ class Package(object): return self.is_installed and \ self._pcache._depcache.is_garbage(self._pkg) + @property + def is_auto_installed(self): + """Return whether the package is marked as automatically installed.""" + return self._pcache._depcache.is_auto_installed(self._pkg) # sizes @DeprecatedProperty @@ -1135,6 +1139,15 @@ class Package(object): sys.stderr.write(("MarkUpgrade() called on a non-upgrable pkg: " "'%s'\n") % self._pkg.name) + def mark_auto(self, auto=True): + """Mark a package as automatically installed. + + Call this function to mark a package as automatically installed. If the + optional parameter *auto* is set to ``False``, the package will not be + marked as automatically installed anymore. The default is ``True``. + """ + self._pcache._depcache.mark_auto(self._pkg, auto) + def commit(self, fprogress, iprogress): """Commit the changes. diff --git a/debian/changelog b/debian/changelog index 4fb6b0de..f0b3efbe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,6 +13,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low properties (Closes: #532338) * apt/cache.py: Correctly handle rootdir on second and later invocations of open() (LP: #320665). + * Add apt_pkg.DepCache.mark_auto() and apt.Package.mark_auto() methods to + mark a package as automatically installed. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -28,7 +30,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Mon, 15 Jun 2009 14:45:06 +0200 + -- Julian Andres Klode Mon, 22 Jun 2009 14:38:19 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/depcache.cc b/python/depcache.cc index d0b233b8..e1514300 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -367,6 +367,23 @@ static PyObject *PkgDepCacheMarkInstall(PyObject *Self,PyObject *Args) return HandleErrors(Py_None); } +static PyObject *PkgDepCacheMarkAuto(PyObject *Self,PyObject *Args) +{ + pkgDepCache *depcache = GetCpp(Self); + + PyObject *PackageObj; + char value = 0; + if (PyArg_ParseTuple(Args,"O!b",&PackageType,&PackageObj, &value) == 0) + return 0; + + pkgCache::PkgIterator &Pkg = GetCpp(PackageObj); + depcache->MarkAuto(Pkg,value); + + Py_INCREF(Py_None); + return HandleErrors(Py_None); +} + + static PyObject *PkgDepCacheIsUpgradable(PyObject *Self,PyObject *Args) { pkgDepCache *depcache = GetCpp(Self); @@ -541,6 +558,7 @@ static PyMethodDef PkgDepCacheMethods[] = {"mark_keep",PkgDepCacheMarkKeep,METH_VARARGS,"Mark package for keep"}, {"mark_delete",PkgDepCacheMarkDelete,METH_VARARGS,"Mark package for delete (optional boolean argument if it should be purged)"}, {"mark_install",PkgDepCacheMarkInstall,METH_VARARGS,"Mark package for Install"}, + {"mark_auto",PkgDepCacheMarkAuto,METH_VARARGS,"mark_auto(pkg: apt_pkg.Package, auto: bool)\n\nMark package as automatically installed."}, {"set_reinstall",PkgDepCacheSetReInstall,METH_VARARGS,"Set if the package should be reinstalled"}, // state information {"is_upgradable",PkgDepCacheIsUpgradable,METH_VARARGS,"Is pkg upgradable"}, -- cgit v1.2.3 From 7c248775da6c86e70a8444630722c92a2dcd676f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 22 Jun 2009 15:53:45 +0200 Subject: python/cache.cc: Drop apt_pkg.Cache.open() and apt_pkg.Cache.close(). Drop these functions, because they cause segfaults and memory leaks. To replace this functionality, simply create/delete a Cache object. This way, reference counting can work. --- debian/changelog | 4 +++- python/cache.cc | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index f0b3efbe..0ef7e38b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low open() (LP: #320665). * Add apt_pkg.DepCache.mark_auto() and apt.Package.mark_auto() methods to mark a package as automatically installed. + * Drop apt_pkg.Cache.open() and apt_pkg.Cache.close(), they cause segfaults + and memory leaks. Simply create a new cache instead. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -30,7 +32,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Mon, 22 Jun 2009 14:38:19 +0200 + -- Julian Andres Klode Mon, 22 Jun 2009 15:49:03 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/cache.cc b/python/cache.cc index 4624dc34..4ce3178c 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -95,6 +95,8 @@ static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args) static PyObject *PkgCacheClose(PyObject *Self,PyObject *Args) { + PyErr_WarnEx(PyExc_DeprecationWarning, "Cache.Close() is deprecated, " + "because it causes segfaults. Delete the Cache instead.", 1); PyObject *CacheFilePy = GetOwner(Self); pkgCacheFile *Cache = GetCpp(CacheFilePy); Cache->Close(); @@ -105,6 +107,9 @@ static PyObject *PkgCacheClose(PyObject *Self,PyObject *Args) static PyObject *PkgCacheOpen(PyObject *Self,PyObject *Args) { + PyErr_WarnEx(PyExc_DeprecationWarning, "Cache.Open() is deprecated, " + "because it causes memory leaks. Create a new Cache instead.", + 1); PyObject *CacheFilePy = GetOwner(Self); pkgCacheFile *Cache = GetCpp(CacheFilePy); @@ -137,8 +142,6 @@ static PyObject *PkgCacheOpen(PyObject *Self,PyObject *Args) static PyMethodDef PkgCacheMethods[] = { {"update",PkgCacheUpdate,METH_VARARGS,"Update the cache"}, - {"open", PkgCacheOpen, METH_VARARGS,"Open the cache"}, - {"close", PkgCacheClose, METH_VARARGS,"Close the cache"}, #ifdef COMPAT_0_7 {"Update",PkgCacheUpdate,METH_VARARGS,"Update the cache"}, {"Open", PkgCacheOpen, METH_VARARGS,"Open the cache"}, -- cgit v1.2.3 From 4b80a5fbfcab291f2386119d40473ec6e782928d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 22 Jun 2009 16:07:31 +0200 Subject: debian/changelog: Add entry about the merge of 0.7.10.4 --- debian/changelog | 1 + 1 file changed, 1 insertion(+) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 0ef7e38b..60ace1f8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low mark a package as automatically installed. * Drop apt_pkg.Cache.open() and apt_pkg.Cache.close(), they cause segfaults and memory leaks. Simply create a new cache instead. + * Merge 0.7.10.4 from unstable [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message -- cgit v1.2.3 From f01f323bf739c8deee17722f5fc6aaf480d7bc13 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 22 Jun 2009 16:17:23 +0200 Subject: debian/control: Update Standards-Version to 3.8.2 --- debian/changelog | 1 + debian/control | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 60ace1f8..843c6b3b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -18,6 +18,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Drop apt_pkg.Cache.open() and apt_pkg.Cache.close(), they cause segfaults and memory leaks. Simply create a new cache instead. * Merge 0.7.10.4 from unstable + * debian/control: Update Standards-Version to 3.8.2 [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/debian/control b/debian/control index 25c58f15..fc48f192 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: python Priority: optional Maintainer: APT Development Team Uploaders: Michael Vogt , Julian Andres Klode -Standards-Version: 3.8.1 +Standards-Version: 3.8.2 XS-Python-Version: all Build-Depends: apt-utils, cdbs, -- cgit v1.2.3 From 6e9b361307e4c024fd882ab4a59d39dfb2b25b60 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 23 Jun 2009 11:29:21 +0200 Subject: python/acquire.cc: Make AcquireFile a subclass of AcquireItem Generalized the code a bit, so we can now access the various attributes of AcquireItem in the AcquireFile (pkgAcqFile is a subclass of pkgAcquire::Item). This will allow us to implement a raw object with a single pointer to an Item later, which we will need for the new progress interface. --- debian/changelog | 1 + python/acquire.cc | 50 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 18 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 843c6b3b..c4486505 100644 --- a/debian/changelog +++ b/debian/changelog @@ -19,6 +19,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low and memory leaks. Simply create a new cache instead. * Merge 0.7.10.4 from unstable * debian/control: Update Standards-Version to 3.8.2 + * Make AcquireFile a subclass of AcquireItem [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/python/acquire.cc b/python/acquire.cc index b0dd2cab..e13e47d6 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -14,20 +14,27 @@ #define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \ { \ - pkgAcquire::ItemIterator &I = GetCpp(Self); \ + pkgAcquire::Item *Itm; \ + if (PyObject_TypeCheck(Self, &PkgAcquireFileType)) { \ + Itm = GetCpp(Self); \ + } else { \ + pkgAcquire::ItemIterator &I = GetCpp(Self); \ + Itm = *I; \ + } \ return Ret; \ } // Define our getters -MkGet(AcquireItemGetComplete,Py_BuildValue("i",(*I)->Complete)); -MkGet(AcquireItemGetDescURI,Safe_FromString((*I)->DescURI().c_str())); -MkGet(AcquireItemGetDestFile,Safe_FromString((*I)->DestFile.c_str())); -MkGet(AcquireItemGetErrorText,Safe_FromString((*I)->ErrorText.c_str())); -MkGet(AcquireItemGetFileSize,Py_BuildValue("i",(*I)->FileSize)); -MkGet(AcquireItemGetID,Py_BuildValue("i",(*I)->ID)); -MkGet(AcquireItemGetIsTrusted,Py_BuildValue("i",(*I)->IsTrusted())); -MkGet(AcquireItemGetLocal,Py_BuildValue("i",(*I)->Local)); -MkGet(AcquireItemGetStatus,Py_BuildValue("i",(*I)->Status)); +MkGet(AcquireItemGetComplete,Py_BuildValue("i",Itm->Complete)); +MkGet(AcquireItemGetDescURI,Safe_FromString(Itm->DescURI().c_str())); +MkGet(AcquireItemGetDestFile,Safe_FromString(Itm->DestFile.c_str())); +MkGet(AcquireItemGetErrorText,Safe_FromString(Itm->ErrorText.c_str())); +MkGet(AcquireItemGetFileSize,Py_BuildValue("i",Itm->FileSize)); +MkGet(AcquireItemGetID,Py_BuildValue("i",Itm->ID)); +MkGet(AcquireItemGetIsTrusted,Py_BuildValue("i",Itm->IsTrusted())); +MkGet(AcquireItemGetLocal,Py_BuildValue("i",Itm->Local)); +MkGet(AcquireItemGetStatus,Py_BuildValue("i",Itm->Status)); + // Constants MkGet(AcquireItemGetStatIdle,Py_BuildValue("i", pkgAcquire::Item::StatIdle)); @@ -43,7 +50,7 @@ static PyGetSetDef AcquireItemGetSet[] = { {"destfile",AcquireItemGetDestFile}, {"error_text",AcquireItemGetErrorText}, {"filesize",AcquireItemGetFileSize}, - {"is",AcquireItemGetID}, + {"id",AcquireItemGetID}, {"is_trusted",AcquireItemGetIsTrusted}, {"local",AcquireItemGetLocal}, {"status",AcquireItemGetStatus}, @@ -75,16 +82,23 @@ static PyGetSetDef AcquireItemGetSet[] = { static PyObject *AcquireItemRepr(PyObject *Self) { - pkgAcquire::ItemIterator &I = GetCpp(Self); + pkgAcquire::Item *Itm; + if (PyObject_TypeCheck(Self, &PkgAcquireFileType)) { + Itm = GetCpp(Self); + } else { + pkgAcquire::ItemIterator &I = GetCpp(Self); + Itm = *I; + } char S[300]; - snprintf(S,sizeof(S),"", - (*I)->Status, (*I)->Complete, (*I)->Local, (*I)->IsTrusted(), - (*I)->FileSize, (*I)->DestFile.c_str(), (*I)->DescURI().c_str(), - (*I)->ID,(*I)->ErrorText.c_str()); + Self->ob_type->tp_name, + Itm->Status, Itm->Complete, Itm->Local, Itm->IsTrusted(), + Itm->FileSize, Itm->DestFile.c_str(), Itm->DescURI().c_str(), + Itm->ID,Itm->ErrorText.c_str()); return PyString_FromString(S); } @@ -383,8 +397,8 @@ PyTypeObject PkgAcquireFileType = 0, // tp_iternext 0, // tp_methods 0, // tp_members - 0, // tp_getset - 0, // tp_base + 0, // tp_getset + &AcquireItemType, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set -- cgit v1.2.3 From c41d1e0c66ab4effdf737ca4c9a9c86c08237451 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 23 Jun 2009 11:39:09 +0200 Subject: python/configuration.cc: Make ConfigurationPtr,ConfigurationSub subclasses of Configuration. This makes isinstance(apt_pkg.config, apt_pkg.Configuration) return True instead of False. --- debian/changelog | 1 + python/configuration.cc | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index c4486505..3209f7ee 100644 --- a/debian/changelog +++ b/debian/changelog @@ -20,6 +20,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Merge 0.7.10.4 from unstable * debian/control: Update Standards-Version to 3.8.2 * Make AcquireFile a subclass of AcquireItem + * Make ConfigurationPtr,ConfigurationSub subclasses of Configuration. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/python/configuration.cc b/python/configuration.cc index 365a35fd..9ef5967b 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -582,6 +582,9 @@ PyTypeObject ConfigurationPtrType = 0, // tp_iter 0, // tp_iternext CnfMethods, // tp_methods + 0, // tp_members + 0, // tp_getset + &ConfigurationType, // tp_base }; PyTypeObject ConfigurationSubType = @@ -618,5 +621,8 @@ PyTypeObject ConfigurationSubType = 0, // tp_iter 0, // tp_iternext CnfMethods, // tp_methods + 0, // tp_members + 0, // tp_getset + &ConfigurationType, // tp_base }; -- cgit v1.2.3 From ca5913fc53580b29034d56dd7942c5cdf5207afe Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 7 Jul 2009 16:57:05 +0200 Subject: debian/control: Build-Depend on libapt-pkg-dev (>= 0.7.22~). --- debian/changelog | 3 ++- debian/control | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 3209f7ee..2b3f0ac1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -21,6 +21,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * debian/control: Update Standards-Version to 3.8.2 * Make AcquireFile a subclass of AcquireItem * Make ConfigurationPtr,ConfigurationSub subclasses of Configuration. + * debian/control: Build-Depend on libapt-pkg-dev (>= 0.7.22~). [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -36,7 +37,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Mon, 22 Jun 2009 15:49:03 +0200 + -- Julian Andres Klode Tue, 07 Jul 2009 16:56:44 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/debian/control b/debian/control index fc48f192..10b9bc31 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ XS-Python-Version: all Build-Depends: apt-utils, cdbs, debhelper (>= 5.0.37.1), - libapt-pkg-dev (>= 0.7.10), + libapt-pkg-dev (>= 0.7.22~), python-all-dbg, python-all-dev, python3.1-dev, -- cgit v1.2.3 From 3770906714c5e73b844514c431ce07fd9ac416fb Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 8 Jul 2009 17:43:01 +0200 Subject: python/apt_pkgmodule.cc: Unify dep handling -- part 1: parse_depends() apt_pkg.parse_[src_]depends() now use CompType instead of CompTypeDeb (i.e. < instead of <<) to match the interface of Version.depends_list_str. --- debian/changelog | 4 ++++ python/apt_pkgmodule.cc | 19 ++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 2b3f0ac1..581e1be1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,6 +22,10 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Make AcquireFile a subclass of AcquireItem * Make ConfigurationPtr,ConfigurationSub subclasses of Configuration. * debian/control: Build-Depend on libapt-pkg-dev (>= 0.7.22~). + * Unification of dependency handling: + - apt_pkg.parse_[src_]depends() now use CompType instead of CompTypeDeb + (i.e. < instead of <<) to match the interface of Version.depends_list_str + [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 9f750996..3f4aae37 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -104,9 +104,10 @@ static char *doc_ParseDepends = "The resulting tuples are (Pkg,Ver,Operation). Each anded dependency is a\n" "list of or'd dependencies\n" "Source depends are evaluated against the curernt arch and only those that\n" -"Match are returned."; +"Match are returned.\n\n" +"apt_pkg.Parse{,Src}Depends() are old forms which return >>,<< instead of >,<"; static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, - bool ParseArchFlags) + bool ParseArchFlags, bool debStyle=false) { string Package; string Version; @@ -143,7 +144,7 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, PyObject *Obj; PyList_Append(LastRow,Obj = Py_BuildValue("sss",Package.c_str(), Version.c_str(), - pkgCache::CompTypeDeb(Op))); + debStyle ? pkgCache::CompTypeDeb(Op) : pkgCache::CompType(Op))); Py_DECREF(Obj); } @@ -165,6 +166,14 @@ static PyObject *ParseDepends(PyObject *Self,PyObject *Args) static PyObject *ParseSrcDepends(PyObject *Self,PyObject *Args) { return RealParseDepends(Self,Args,true); +} +static PyObject *ParseDepends_old(PyObject *Self,PyObject *Args) +{ + return RealParseDepends(Self,Args,false, true); +} +static PyObject *ParseSrcDepends_old(PyObject *Self,PyObject *Args) +{ + return RealParseDepends(Self,Args,true, true); } /*}}}*/ // md5sum - Compute the md5sum of a file or string /*{{{*/ @@ -444,8 +453,8 @@ static PyMethodDef methods[] = {"parse_depends",ParseDepends,METH_VARARGS,doc_ParseDepends}, {"parse_src_depends",ParseSrcDepends,METH_VARARGS,doc_ParseDepends}, #ifdef COMPAT_0_7 - {"ParseDepends",ParseDepends,METH_VARARGS,doc_ParseDepends}, - {"ParseSrcDepends",ParseSrcDepends,METH_VARARGS,doc_ParseDepends}, + {"ParseDepends",ParseDepends_old,METH_VARARGS,doc_ParseDepends}, + {"ParseSrcDepends",ParseSrcDepends_old,METH_VARARGS,doc_ParseDepends}, #endif // Stuff -- cgit v1.2.3 From d2423e2c28df63cb0a235f822a9588f8a221600a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 8 Jul 2009 20:18:36 +0200 Subject: python/pkgsrcrecords.cc: Unify dep handling -- part 2: SourceRecords.build_depends Change apt_pkg.SourceRecords.build_depends to match exactly the interface of Version.depends_list_str just with different keys (e.g. Build-Depends). + Closes: #468123 - there is no need anymore for binding CompType or CompTypeDeb, because we don't return integer values for CompType anymore. --- debian/changelog | 6 +++++- python/pkgsrcrecords.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 581e1be1..8bc3e320 100644 --- a/debian/changelog +++ b/debian/changelog @@ -25,7 +25,11 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Unification of dependency handling: - apt_pkg.parse_[src_]depends() now use CompType instead of CompTypeDeb (i.e. < instead of <<) to match the interface of Version.depends_list_str - + - apt_pkg.SourceRecords.build_depends matches exactly the interface of + Version.depends_list_str just with different keys (e.g. Build-Depends). + + Closes: #468123 - there is no need anymore for binding CompType or + CompTypeDeb, because we don't return integer values for CompType + anymore. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc index 187050b7..06fd4e3b 100644 --- a/python/pkgsrcrecords.cc +++ b/python/pkgsrcrecords.cc @@ -151,6 +151,54 @@ static PyObject *PkgSrcRecordsGetFiles(PyObject *Self,void*) { } static PyObject *PkgSrcRecordsGetBuildDepends(PyObject *Self,void*) { + PkgSrcRecordsStruct &Struct = GetStruct(Self,"BuildDepends"); + if (Struct.Last == 0) + return 0; + + PyObject *Dict = PyDict_New(); + PyObject *Dep = 0; + PyObject *LastDep = 0; + PyObject *OrGroup = 0; + + vector bd; + if(!Struct.Last->BuildDepends(bd, false /* arch-only*/)) + return NULL; // error + + PyObject *v; + for(unsigned int i=0;i Date: Sun, 12 Jul 2009 19:07:55 +0200 Subject: python/hashes.cc: Introduce the Hashes class. The Hashes class is a function which calculates all supported hashes for one input. DebImg will use this for calculating the hashes of files. --- debian/changelog | 3 +- doc/source/apt_pkg.rst | 26 +++++++-- python/apt_pkgmodule.cc | 1 + python/apt_pkgmodule.h | 1 + python/hashes.cc | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ python/makefile | 5 +- 6 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 python/hashes.cc (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 8bc3e320..1f43cc8c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -30,6 +30,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low + Closes: #468123 - there is no need anymore for binding CompType or CompTypeDeb, because we don't return integer values for CompType anymore. + * Introduce apt_pkg.Hashes class. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -45,7 +46,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Tue, 07 Jul 2009 16:56:44 +0200 + -- Julian Andres Klode Sun, 12 Jul 2009 18:51:57 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/doc/source/apt_pkg.rst b/doc/source/apt_pkg.rst index 2af934a0..9a14266e 100644 --- a/doc/source/apt_pkg.rst +++ b/doc/source/apt_pkg.rst @@ -1139,15 +1139,31 @@ installation. the file using the parameter *destfile*. You can not combine both. +Hashes +------ +The apt_pkg module also provides several hash functions. If you develop +applications with python-apt it is often easier to use these functions instead +of the ones provides in Python's :mod:`hashlib` module. +.. class:: Hashes(object) + Calculate all supported hashes of the object. *object* may either be a + string, in which cases the hashes of the string are calculated, or a + :class:`file()` object or file descriptor, in which case the hashes of + its contents is calculated. The calculated hashes are then available via + attributes: + .. attribute:: md5 -Hash functions --------------- -The apt_pkg module also provides several hash functions. If you develop -applications with python-apt it is often easier to use these functions instead -of the ones provides in Python's :mod:`hashlib` module. + The MD5 hash of the data, as string. + + .. attribute:: sha1 + + The SHA1 hash of the data, as string. + + .. attribute:: sha256 + + The SHA256 hash of the data, as string. .. function:: md5sum(object) diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 3f4aae37..4c0fd5ed 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -618,6 +618,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"IndexRecords",&PyIndexRecords_Type); ADDTYPE(Module,"HashString",&PyHashString_Type); ADDTYPE(Module,"Policy",&PyPolicy_Type); + ADDTYPE(Module,"Hashes",&PyHashes_Type); // Tag file constants PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", CharCharToList(TFRewritePackageOrder)); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 21355072..1a2f1a1a 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -116,5 +116,6 @@ extern PyTypeObject PyIndexRecords_Type; // Policy extern PyTypeObject PyPolicy_Type; +extern PyTypeObject PyHashes_Type; #endif diff --git a/python/hashes.cc b/python/hashes.cc new file mode 100644 index 00000000..a1ace6fc --- /dev/null +++ b/python/hashes.cc @@ -0,0 +1,136 @@ +/* hashes.cc - Wrapper around apt-pkg's Hashes. + * + * Copyright 2009 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 "generic.h" +#include "apt_pkgmodule.h" +#include + +static PyObject *hashes_new(PyTypeObject *type,PyObject *args, + PyObject *kwds) +{ + return CppPyObject_NEW(type); +} + +static int hashes_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *object = 0; + int Fd; + char *kwlist[] = {"object", NULL}; + + if (PyArg_ParseTupleAndKeywords(args, kwds, "|O:__init__", kwlist, + &object) == 0) + return -1; + if (object == 0) + return 0; + Hashes &hashes = GetCpp(self); + + if (PyBytes_Check(object) != 0) { + char *s; + Py_ssize_t len; + PyBytes_AsStringAndSize(object, &s, &len); + hashes.Add((const unsigned char*)s, len); + } + else if ((Fd = PyObject_AsFileDescriptor(object)) != -1) { + struct stat St; + if (fstat(Fd, &St) != 0 || hashes.AddFD(Fd, St.st_size) == false) { + PyErr_SetFromErrno(PyExc_SystemError); + return -1; + } + } + else { + PyErr_SetString(PyExc_TypeError, "__init__() only understand strings" + " and files"); + return -1; + } + return 0; +} + +static PyObject *hashes_get_md5(PyObject *self, void*) +{ + return CppPyString(GetCpp(self).MD5.Result().Value()); +} + +static PyObject *hashes_get_sha1(PyObject *self, void*) +{ + return CppPyString(GetCpp(self).SHA1.Result().Value()); +} + +static PyObject *hashes_get_sha256(PyObject *self, void*) +{ + return CppPyString(GetCpp(self).SHA256.Result().Value()); +} + +static PyGetSetDef hashes_getset[] = { + {"md5",hashes_get_md5,0,"The MD5Sum of the file as a string."}, + {"sha1",hashes_get_sha1,0,"The SHA1Sum of the file as a string."}, + {"sha256",hashes_get_sha256,0,"The SHA256Sum of the file as a string."}, + {} +}; + +static char *hashes_doc = + "Hashes([object: (bytes, file)])\n\n" + "Calculate hashes for the given object. It can be used to create all\n" + "supported hashes for a file.\n\n" + "The parameter *object* can be a bytes (3.X) / str (2.X) object, or an\n" + "object providing the fileno() method or an integer describing a file\n" + "descriptor."; + +PyTypeObject PyHashes_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Hashes", // 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 + 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, + hashes_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + hashes_getset, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + hashes_init, // tp_init + 0, // tp_alloc + hashes_new, // tp_new +}; diff --git a/python/makefile b/python/makefile index 6799d749..fff3a2e8 100644 --- a/python/makefile +++ b/python/makefile @@ -11,8 +11,9 @@ SLIBS = -lapt-pkg LIB_MAKES = apt-pkg/makefile APT_PKG_SRC = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \ cache.cc pkgrecords.cc pkgsrcrecords.cc sourcelist.cc \ - depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \ - indexfile.cc metaindex.cc hashstring.cc indexrecords.cc policy.cc + depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \ + indexfile.cc metaindex.cc hashstring.cc indexrecords.cc \ + policy.cc hashes.cc SOURCE := $(APT_PKG_SRC) include $(PYTHON_H) progress.h -- cgit v1.2.3 From b0abeea43f6e51c452af68d8ec9bf3d0f701d772 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 12 Jul 2009 21:22:58 +0200 Subject: python/acquire.cc: Fix segmentation faults, introduce PyAcquireObject. Make AcquireItem objects raise ValueError instead of segfaulting when the Acquire() object is shut down or the main object (e.g. AcquireFile) is deallocated. This is implemented by using a vector of the AcquireItem objects, and setting AcquireItem->Object = NULL, when the memory 'Object' previously pointed to is going to be deleted. --- debian/changelog | 4 ++- python/acquire.cc | 96 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 73 insertions(+), 27 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 1f43cc8c..304237c1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -31,6 +31,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low CompTypeDeb, because we don't return integer values for CompType anymore. * Introduce apt_pkg.Hashes class. + * Make AcquireItem objects raise ValueError instead of segfaulting when the Acquire() + object is shut down or the main object (e.g. AcquireFile) is deallocated. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -46,7 +48,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Sun, 12 Jul 2009 18:51:57 +0200 + -- Julian Andres Klode Sun, 12 Jul 2009 21:19:40 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/acquire.cc b/python/acquire.cc index 6c6c2ea4..054956ea 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -12,15 +12,27 @@ #include +typedef CppPyObject PyAcquireItemObject; + +// Keep a vector to PyAcquireItemObject pointers, so we can set the Object +// pointers to NULL when deallocating the main object (mostly AcquireFile). +struct PyAcquireObject : public CppPyObject { + vector items; +}; + +inline pkgAcquire::Item *PyAcquireItem_ToCpp(PyObject *self) { + pkgAcquire::Item *itm = GetCpp(self); + if (itm == 0) + PyErr_SetString(PyExc_ValueError, "Acquire() has been shut down or " + "the AcquireFile() object has been deallocated."); + return itm; +} + #define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \ { \ - pkgAcquire::Item *Itm; \ - if (PyObject_TypeCheck(Self, &PkgAcquireFileType)) { \ - Itm = GetCpp(Self); \ - } else { \ - pkgAcquire::ItemIterator &I = GetCpp(Self); \ - Itm = *I; \ - } \ + pkgAcquire::Item *Itm = PyAcquireItem_ToCpp(Self); \ + if (Itm == 0) \ + return 0; \ return Ret; \ } @@ -30,7 +42,7 @@ MkGet(AcquireItemGetDescURI,Safe_FromString(Itm->DescURI().c_str())); MkGet(AcquireItemGetDestFile,Safe_FromString(Itm->DestFile.c_str())); MkGet(AcquireItemGetErrorText,Safe_FromString(Itm->ErrorText.c_str())); MkGet(AcquireItemGetFileSize,Py_BuildValue("i",Itm->FileSize)); -MkGet(AcquireItemGetID,Py_BuildValue("i",Itm->ID)); +MkGet(AcquireItemGetID,Py_BuildValue("i",Itm)); MkGet(AcquireItemGetIsTrusted,Py_BuildValue("i",Itm->IsTrusted())); MkGet(AcquireItemGetLocal,Py_BuildValue("i",Itm->Local)); MkGet(AcquireItemGetStatus,Py_BuildValue("i",Itm->Status)); @@ -82,14 +94,9 @@ static PyGetSetDef AcquireItemGetSet[] = { static PyObject *AcquireItemRepr(PyObject *Self) { - pkgAcquire::Item *Itm; - if (PyObject_TypeCheck(Self, &PkgAcquireFileType)) { - Itm = GetCpp(Self); - } else { - pkgAcquire::ItemIterator &I = GetCpp(Self); - Itm = *I; - } - + pkgAcquire::Item *Itm = PyAcquireItem_ToCpp(Self); + if (Itm == 0) + return 0; char S[300]; snprintf(S,sizeof(S),"<%s object: " "Status: %i Complete: %i Local: %i IsTrusted: %i " @@ -102,15 +109,45 @@ static PyObject *AcquireItemRepr(PyObject *Self) return PyString_FromString(S); } +static void AcquireItemDealloc(PyObject *self) { + pkgAcquire::Item *file = GetCpp(self); + PyAcquireObject *owner = (PyAcquireObject *)GetOwner(self); + vector &items = owner->items; + bool DeletePtr = !((CppPyObject *)self)->NoDelete; + + // Cleanup the other objects as well... + for (vector::iterator I = items.begin(); + I != items.end(); I++) { + // If it is the current object, remove it from the vector. + if ((*I) == self) { + items.erase(I); + I--; // erase() moved it one forward, move back + } + // If we delete the object below, set all other pointers to it to NULL, + // and remove them from the vector. + else if (DeletePtr && (*I)->Object == file) { + if ((*I) != self) + (*I)->Object = NULL; + items.erase(I); + I--; // erase() moved it one forward, move back + } + } +#ifdef ALLOC_DEBUG + std::cerr << "ITEMS: " << items.size() << "\n"; +#endif + CppOwnedDeallocPtr(self); +} + + PyTypeObject AcquireItemType = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.AcquireItem", // tp_name - sizeof(CppOwnedPyObject), // tp_basicsize + sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc, // tp_dealloc + AcquireItemDealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -139,6 +176,7 @@ PyTypeObject AcquireItemType = }; + static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args) { pkgAcquire *fetcher = GetCpp(Self); @@ -161,6 +199,11 @@ static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args) fetcher->Shutdown(); + vector items = ((PyAcquireObject *)Self)->items; + for (vector::iterator I = items.begin(); + I != items.end(); I++) + (*I)->Object = NULL; + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -194,12 +237,12 @@ static PyObject *PkgAcquireGetItems(PyObject *Self,void*) for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin(); I != fetcher->ItemsEnd(); I++) { - PyObject *Obj; - Obj = CppOwnedPyObject_NEW(Self, - &AcquireItemType,I); + PyAcquireItemObject *Obj; + Obj = CppOwnedPyObject_NEW(Self,&AcquireItemType,*I); + Obj->NoDelete = true; PyList_Append(List,Obj); + ((PyAcquireObject *)Self)->items.push_back(Obj); Py_DECREF(Obj); - } return List; } @@ -266,7 +309,7 @@ PyTypeObject PkgAcquireType = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Acquire", // tp_name - sizeof(CppPyObject), // tp_basicsize + sizeof(PyAcquireObject), // tp_basicsize 0, // tp_itemsize // Methods CppDeallocPtr, // tp_dealloc @@ -341,6 +384,8 @@ static PyObject *PkgAcquireFileNew(PyTypeObject *type, PyObject *Args, PyObject destFile); // short-desc CppOwnedPyObject *AcqFileObj = CppOwnedPyObject_NEW(pyfetcher, type); AcqFileObj->Object = af; + ((PyAcquireObject *)pyfetcher)->items.push_back((PyAcquireItemObject *)AcqFileObj); + return AcqFileObj; } @@ -359,9 +404,7 @@ PyTypeObject PkgAcquireFileType = sizeof(CppOwnedPyObject),// tp_basicsize 0, // tp_itemsize // Methods - // Not ..Ptr, because this would cause the item to be removed from the - // fetcher, which would be incompatible to previous behaviour. - CppOwnedDealloc, // tp_dealloc + AcquireItemDealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -431,6 +474,7 @@ PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject * kwds) destFile); // short-desc CppPyObject *AcqFileObj = CppPyObject_NEW(&PkgAcquireFileType); AcqFileObj->Object = af; + AcqFileObj->NoDelete = true; return AcqFileObj; } -- cgit v1.2.3 From 8430dbf041ce70dcba81101678beee0492252fd2 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 14 Jul 2009 20:43:56 +0200 Subject: python/configuration.cc: Unify all Configuration,ConfigurationPtr,ConfigurationSub into one type. This makes the whole API easier. The disadvantage is that we require 8 bytes (??) more per object for the owner object pointer, which is NULL for most cases (the only exception being objects created by Configuration.sub_tree). --- debian/changelog | 3 +- python/apt_pkgmodule.cc | 9 ++-- python/apt_pkgmodule.h | 6 +-- python/configuration.cc | 116 ++++-------------------------------------------- 4 files changed, 15 insertions(+), 119 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 304237c1..4ae6e574 100644 --- a/debian/changelog +++ b/debian/changelog @@ -33,6 +33,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Introduce apt_pkg.Hashes class. * Make AcquireItem objects raise ValueError instead of segfaulting when the Acquire() object is shut down or the main object (e.g. AcquireFile) is deallocated. + * Unify all Configuration,ConfigurationPtr,ConfigurationSub into one type. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -48,7 +49,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Sun, 12 Jul 2009 21:19:40 +0200 + -- Julian Andres Klode Tue, 14 Jul 2009 20:42:03 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 3f18f785..e4fd0dfc 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -527,8 +527,7 @@ extern "C" void initapt_pkg() #endif { // Finalize our types to add slots, etc. - if (PyType_Ready(&PyConfigurationPtr_Type) == -1) INIT_ERROR; - if (PyType_Ready(&PyConfigurationSub_Type) == -1) INIT_ERROR; + if (PyType_Ready(&PyConfiguration_Type) == -1) INIT_ERROR; if (PyType_Ready(&PyCacheFile_Type) == -1) INIT_ERROR; // Initialize the module @@ -539,8 +538,10 @@ extern "C" void initapt_pkg() #endif // Global variable linked to the global configuration class - CppPyObject *Config = CppPyObject_NEW(&PyConfigurationPtr_Type); + CppOwnedPyObject *Config = CppOwnedPyObject_NEW(NULL, &PyConfiguration_Type); Config->Object = _config; + // Global configuration, should never be deleted. + Config->NoDelete = true; PyModule_AddObject(Module,"config",Config); #ifdef COMPAT_0_7 Py_INCREF(Config); @@ -568,8 +569,6 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"Cdrom",&PyCdrom_Type); /* ========================= configuration.cc ========================= */ ADDTYPE(Module,"Configuration",&PyConfiguration_Type); - //ADDTYPE(Module,"ConfigurationSub",&PyConfigurationSub_Type); // NO __new__() - //ADDTYPE(Module,"ConfigurationPtr",&PyConfigurationPtr_Type); // NO __new__() /* ========================= depcache.cc ========================= */ ADDTYPE(Module,"ActionGroup",&PyActionGroup_Type); ADDTYPE(Module,"DepCache",&PyDepCache_Type); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 7b835ca8..f77c5e73 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -14,12 +14,8 @@ #include // Configuration Stuff -#define Configuration_Check(op) ((op)->ob_type == &PyConfiguration_Type || \ - (op)->ob_type == &PyConfigurationPtr_Type || \ - (op)->ob_type == &PyConfigurationSub_Type) +#define Configuration_Check(op) ((op)->ob_type == &PyConfiguration_Type) extern PyTypeObject PyConfiguration_Type; -extern PyTypeObject PyConfigurationPtr_Type; -extern PyTypeObject PyConfigurationSub_Type; extern PyTypeObject PyVersion_Type; extern char *doc_LoadConfig; diff --git a/python/configuration.cc b/python/configuration.cc index ba075133..e7e31cc8 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -5,11 +5,8 @@ Configuration - Binding for the configuration object. - There are three seperate classes.. - Configuration - A stand alone configuration instance - ConfigurationPtr - A pointer to a configuration instance, used only - for the global instance (_config) - ConfigurationSub - A subtree - has a reference to its owner. + The Configuration object can have an owner (a parent Configuration object), + and it always uses a pointer. The wrapping is mostly 1:1 with the C++ code, but there are additions to wrap the linked tree walking into nice flat sequence walking. @@ -25,33 +22,13 @@ #include /*}}}*/ -/* If we create a sub tree then it is of this type, the Owner is used - to manage reference counting. */ -struct SubConfiguration : public CppPyObject -{ - PyObject *Owner; -}; - - /*}}}*/ -// CnfSubFree - Free a sub configuration /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void CnfSubFree(PyObject *Obj) -{ - SubConfiguration *Self = (SubConfiguration *)Obj; - Py_DECREF(Self->Owner); - CppDealloc(Obj); -} - /*}}}*/ // GetSelf - Convert PyObject to Configuration /*{{{*/ // --------------------------------------------------------------------- /* */ static inline Configuration &GetSelf(PyObject *Obj) { - if (Obj->ob_type == &PyConfigurationPtr_Type) - return *GetCpp(Obj); - return GetCpp(Obj); + return *GetCpp(Obj); } /*}}}*/ @@ -160,13 +137,8 @@ static PyObject *CnfSubTree(PyObject *Self,PyObject *Args) return 0; } - // Create a new sub configuration. - SubConfiguration *New = (SubConfiguration*)(&PyConfigurationSub_Type) - ->tp_alloc(&PyConfigurationSub_Type,0); - new (&New->Object) Configuration(Itm); - New->Owner = Self; - Py_INCREF(Self); - return New; + return CppOwnedPyObject_NEW(Self,&PyConfiguration_Type, + new Configuration(Itm)); } // Return a list of items at a specific level @@ -495,7 +467,7 @@ static PyObject *CnfNew(PyTypeObject *type, PyObject *args, PyObject *kwds) { char *kwlist[] = {NULL}; if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0) return 0; - return CppPyObject_NEW(type); + return CppOwnedPyObject_NEW(NULL, type, new Configuration()); } // Type for a Normal Configuration object @@ -505,10 +477,10 @@ PyTypeObject PyConfiguration_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Configuration", // tp_name - sizeof(CppPyObject), // tp_basicsize + sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc, // tp_dealloc + CppOwnedDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -545,75 +517,3 @@ PyTypeObject PyConfiguration_Type = CnfNew, // tp_new }; -PyTypeObject PyConfigurationPtr_Type = -{ - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.ConfigurationPtr", // tp_name - sizeof(CppPyObject), // tp_basicsize - 0, // tp_itemsize - // Methods - (destructor)PyObject_Free, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - &ConfigurationSeq, // tp_as_sequence - &ConfigurationMap, // 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 - "ConfigurationPtr Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - CnfMethods, // tp_methods - 0, // tp_members - 0, // tp_getset - &PyConfiguration_Type, // tp_base -}; - -PyTypeObject PyConfigurationSub_Type = -{ - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.ConfigurationSub", // tp_name - sizeof(SubConfiguration), // tp_basicsize - 0, // tp_itemsize - // Methods - CnfSubFree, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - &ConfigurationSeq, // tp_as_sequence - &ConfigurationMap, // 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 - "ConfigurationSub Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - CnfMethods, // tp_methods - 0, // tp_members - 0, // tp_getset - &PyConfiguration_Type, // tp_base -}; - -- cgit v1.2.3 From 360477dcc304b8a18c467e59435d8c766bbb76bb Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 14:14:44 +0200 Subject: python/python-apt.h: Introduce the C++ API The C++ API provides support for creating Python objects from C++ objects given by pointer or reference (depending on the implementation of the Python object) and for retrieving the underlying C++ object from the Python object and for checking the type of the Python object. --- debian/changelog | 1 + debian/control | 11 ++ debian/python-apt-dev.examples | 1 + debian/python-apt-dev.install | 2 + doc/client-example.cc | 46 ++++++++ python/apt_pkgmodule.cc | 38 ++++++ python/apt_pkgmodule.h | 4 +- python/hashstring.cc | 5 - python/python-apt.h | 259 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 360 insertions(+), 7 deletions(-) create mode 100644 debian/python-apt-dev.examples create mode 100644 debian/python-apt-dev.install create mode 100644 doc/client-example.cc create mode 100644 python/python-apt.h (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 4ae6e574..415ebdd2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low [ Julian Andres Klode ] * Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141) * Add apt_pkg.Policy class (Closes: #382725) + * Provide a C++ API in the package python-apt-dev (Closes: #334923) * Allow types providing __new__() to be subclassed. * Bugfix: Delete pointers correctly, fixing memory leaks. (LP: #370149) * apt/package.py: Return VersionList objects in Package.versions, which diff --git a/debian/control b/debian/control index 10b9bc31..a16ae10e 100644 --- a/debian/control +++ b/debian/control @@ -54,3 +54,14 @@ Description: Python interface to libapt-pkg (debug extension) variety of functions. . This package contains the extension built for the Python debug interpreter. + +Package: python-apt-dev +Architecture: all +Depends: python-apt (>= ${source:Version}), libapt-pkg-dev (>= 0.7.10) +Description: Python interface to libapt-pkg (development files) + The apt_pkg Python interface will provide full access to the internal + libapt-pkg structures allowing Python programs to easily perform a + variety of functions. + . + This package contains the header files needed to use python-apt objects from + C++ applications. diff --git a/debian/python-apt-dev.examples b/debian/python-apt-dev.examples new file mode 100644 index 00000000..39f7bf97 --- /dev/null +++ b/debian/python-apt-dev.examples @@ -0,0 +1 @@ +doc/client-example.cc diff --git a/debian/python-apt-dev.install b/debian/python-apt-dev.install new file mode 100644 index 00000000..2a1405fd --- /dev/null +++ b/debian/python-apt-dev.install @@ -0,0 +1,2 @@ +python/python-apt.h usr/include/python-apt/ +python/generic.h usr/include/python-apt/ diff --git a/doc/client-example.cc b/doc/client-example.cc new file mode 100644 index 00000000..7fa6672f --- /dev/null +++ b/doc/client-example.cc @@ -0,0 +1,46 @@ +/* + * client-example.cc - A simple example for using the python-apt C++ API. + * + * Copyright 2009 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 + +int main(int argc, char *argv[]) { + Py_Initialize(); + if (import_apt_pkg() < 0) + return 1; + + // Initialize a module. + PyObject *Module = Py_InitModule("client", NULL); + + // Create a HashString, which will be added to the module. + HashString *hash = new HashString("0966a120bb936bdc6fdeac445707aa6b"); + // Create a Python object for the hashstring and add it to the module + PyModule_AddObject(Module, "hash", PyHashString_FromCpp(hash)); + + // Another example: Add the HashString type to the module. + Py_INCREF(&PyHashString_Type); + PyModule_AddObject(Module, "HashString", (PyObject*)(&PyHashString_Type)); + + // Run IPython, adding the client module to the namespace. + PySys_SetArgv(argc, argv); + PyRun_SimpleString("from IPython.Shell import start\n"); + PyRun_SimpleString("import client\n"); + PyRun_SimpleString("start(user_ns=dict(client=client)).mainloop()\n"); + Py_Finalize(); +} diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index e4fd0dfc..bc2f4258 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -498,6 +498,38 @@ static PyMethodDef methods[] = {} }; +static struct _PyAptPkgAPIStruct API = { + &PyAcquire_Type, // acquire_type + &PyAcquireFile_Type, // acquirefile_type + &PyAcquireItem_Type, // acquireitem_type + &PyActionGroup_Type, // actiongroup_type + &PyCache_Type, // cache_type + &PyCacheFile_Type, // cachefile_type + &PyCdrom_Type, // cdrom_type + &PyConfiguration_Type, // configuration_type + &PyDepCache_Type, // depcache_type + &PyDependency_Type, // dependency_type + &PyDependencyList_Type, // dependencylist_type + &PyDescription_Type, // description_type + &PyHashes_Type, // hashes_type + &PyHashString_Type, // hashstring_type + &PyIndexRecords_Type, // indexrecords_type + &PyMetaIndex_Type, // metaindex_type + &PyPackage_Type, // package_type + &PyPackageFile_Type, // packagefile_type + &PyPackageIndexFile_Type, // packageindexfile_type + &PyPackageList_Type, // packagelist_type + &PyPackageManager_Type, // packagemanager_type + &PyPackageRecords_Type, // packagerecords_type + &PyPolicy_Type, // policy_type + &PyProblemResolver_Type, // problemresolver_type + &PySourceList_Type, // sourcelist_type + &PySourceRecords_Type, // sourcerecords_type + &PyTagFile_Type, // tagfile_type + &PyTagSection_Type, // tagsection_type + &PyVersion_Type, // version_type +}; + #define ADDTYPE(mod,name,type) { \ if (PyType_Ready(type) == -1) INIT_ERROR; \ @@ -596,6 +628,12 @@ extern "C" void initapt_pkg() PyModule_AddObject(Module,"REWRITE_SOURCE_ORDER", CharCharToList(TFRewriteSourceOrder)); +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 + PyObject *PyCapsule = PyCapsule_New(&API, "apt_pkg._C_API", NULL); +#else + PyObject *PyCapsule = PyCObject_FromVoidPtr(&API, NULL); +#endif + PyModule_AddObject(Module, "_C_API", PyCapsule); // Version.. PyModule_AddStringConstant(Module,"VERSION",(char *)pkgVersion); PyModule_AddStringConstant(Module,"LIB_VERSION",(char *)pkgLibVersion); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index f77c5e73..97be5d5c 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -104,7 +104,6 @@ extern PyTypeObject PyPackageIndexFile_Type; extern PyTypeObject PyMetaIndex_Type; // HashString -PyObject *PyHashString_FromCpp(HashString *obj); extern PyTypeObject PyHashString_Type; // IndexRecord @@ -113,5 +112,6 @@ extern PyTypeObject PyIndexRecords_Type; // Policy extern PyTypeObject PyPolicy_Type; extern PyTypeObject PyHashes_Type; - +#include "python-apt.h" #endif + diff --git a/python/hashstring.cc b/python/hashstring.cc index d303049a..b76dc127 100644 --- a/python/hashstring.cc +++ b/python/hashstring.cc @@ -39,11 +39,6 @@ static PyObject *HashString_NEW(PyTypeObject *type,PyObject *Args, return PyObj; } -PyObject *PyHashString_FromCpp(HashString *obj) -{ - return CppPyObject_NEW(&PyHashString_Type, obj); -} - static PyObject *HashString_Repr(PyObject *self) { HashString *hash = GetCpp(self); diff --git a/python/python-apt.h b/python/python-apt.h new file mode 100644 index 00000000..557f5a3b --- /dev/null +++ b/python/python-apt.h @@ -0,0 +1,259 @@ +/* + * python-apt.h - Header file for the public interface. + * + * Copyright 2009 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. + */ + +#ifndef PYTHON_APT_H +#define PYTHON_APT_H +#include +#include +#include "generic.h" + +struct _PyAptPkgAPIStruct { + PyTypeObject *acquire_type; + PyTypeObject *acquirefile_type; + PyTypeObject *acquireitem_type; + PyTypeObject *actiongroup_type; + PyTypeObject *cache_type; + PyTypeObject *cachefile_type; + PyTypeObject *cdrom_type; + PyTypeObject *configuration_type; + PyTypeObject *depcache_type; + PyTypeObject *dependency_type; + PyTypeObject *dependencylist_type; + PyTypeObject *description_type; + PyTypeObject *hashes_type; + PyTypeObject *hashstring_type; + PyTypeObject *indexrecords_type; + PyTypeObject *metaindex_type; + PyTypeObject *package_type; + PyTypeObject *packagefile_type; + PyTypeObject *packageindexfile_type; + PyTypeObject *packagelist_type; + PyTypeObject *packagemanager_type; + PyTypeObject *packagerecords_type; + PyTypeObject *policy_type; + PyTypeObject *problemresolver_type; + PyTypeObject *sourcelist_type; + PyTypeObject *sourcerecords_type; + PyTypeObject *tagfile_type; + PyTypeObject *tagsection_type; + PyTypeObject *version_type; +}; + +# ifndef APT_PKGMODULE_H +# define PyAcquire_Type *(_PyAptPkg_API->acquire_type) +# define PyAcquireFile_Type *(_PyAptPkg_API->acquirefile_type) +# define PyAcquireItem_Type *(_PyAptPkg_API->acquireitem_type) +# define PyActionGroup_Type *(_PyAptPkg_API->actiongroup_type) +# define PyCache_Type *(_PyAptPkg_API->cache_type) +# define PyCacheFile_Type *(_PyAptPkg_API->cachefile_type) +# define PyCdrom_Type *(_PyAptPkg_API->cdrom_type) +# define PyConfiguration_Type *(_PyAptPkg_API->configuration_type) +# define PyDepCache_Type *(_PyAptPkg_API->depcache_type) +# define PyDependency_Type *(_PyAptPkg_API->dependency_type) +# define PyDependencyList_Type *(_PyAptPkg_API->dependencylist_type) +# define PyDescription_Type *(_PyAptPkg_API->description_type) +# define PyHashes_Type *(_PyAptPkg_API->hashes_type) +# define PyHashString_Type *(_PyAptPkg_API->hashstring_type) +# define PyIndexRecords_Type *(_PyAptPkg_API->indexrecords_type) +# define PyMetaIndex_Type *(_PyAptPkg_API->metaindex_type) +# define PyPackage_Type *(_PyAptPkg_API->package_type) +# define PyPackageFile_Type *(_PyAptPkg_API->packagefile_type) +# define PyPackageIndexFile_Type *(_PyAptPkg_API->packageindexfile_type) +# define PyPackageList_Type *(_PyAptPkg_API->packagelist_type) +# define PyPackageManager_Type *(_PyAptPkg_API->packagemanager_type) +# define PyPackageRecords_Type *(_PyAptPkg_API->packagerecords_type) +# define PyPolicy_Type *(_PyAptPkg_API->policy_type) +# define PyProblemResolver_Type *(_PyAptPkg_API->problemresolver_type) +# define PySourceList_Type *(_PyAptPkg_API->sourcelist_type) +# define PySourceRecords_Type *(_PyAptPkg_API->sourcerecords_type) +# define PyTagFile_Type *(_PyAptPkg_API->tagfile_type) +# define PyTagSection_Type *(_PyAptPkg_API->tagsection_type) +# define PyVersion_Type *(_PyAptPkg_API->version_type) + +// Creating + +static struct _PyAptPkgAPIStruct *_PyAptPkg_API; + +static int import_apt_pkg(void) { +# if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 + _PyAptPkg_API = (_PyAptPkgAPIStruct *)PyCapsule_Import("apt_pkg._C_API", 0); + return (_PyAptPkg_API != NULL) ? 0 : -1; +# else + + PyObject *module = PyImport_ImportModule("apt_pkg"); + + if (module == NULL) { + return -1; + } + if (module != NULL) { + PyObject *c_api_object = PyObject_GetAttrString(module, "_C_API"); + if (c_api_object == NULL) + return -1; + if (PyCObject_Check(c_api_object)) + _PyAptPkg_API = (struct _PyAptPkgAPIStruct *)PyCObject_AsVoidPtr(c_api_object); + Py_DECREF(c_api_object); + } + return 0; +# endif // PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 +} +# endif // APT_PKGMODULE_H + +// Checking macros. +# define PyAcquire_Check(op) PyObject_TypeCheck(op, &PyAcquire_Type) +# define PyAcquireFile_Check(op) PyObject_TypeCheck(op, &PyAcquireFile_Type) +# define PyAcquireItem_Check(op) PyObject_TypeCheck(op, &PyAcquireItem_Type) +# define PyActionGroup_Check(op) PyObject_TypeCheck(op, &PyActionGroup_Type) +# define PyCache_Check(op) PyObject_TypeCheck(op, &PyCache_Type) +# define PyCacheFile_Check(op) PyObject_TypeCheck(op, &PyCacheFile_Type) +# define PyCdrom_Check(op) PyObject_TypeCheck(op, &PyCdrom_Type) +# define PyConfiguration_Check(op) PyObject_TypeCheck(op, &PyConfiguration_Type) +# define PyDepCache_Check(op) PyObject_TypeCheck(op, &PyDepCache_Type) +# 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 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) +# define PyMetaIndex_Check(op) PyObject_TypeCheck(op, &PyMetaIndex_Type) +# define PyPackage_Check(op) PyObject_TypeCheck(op, &PyPackage_Type) +# define PyPackageFile_Check(op) PyObject_TypeCheck(op, &PyPackageFile_Type) +# define PyPackageIndexFile_Check(op) PyObject_TypeCheck(op, &PyPackageIndexFile_Type) +# define PyPackageList_Check(op) PyObject_TypeCheck(op, &PyPackageList_Type) +# define PyPackageManager_Check(op) PyObject_TypeCheck(op, &PyPackageManager_Type) +# define PyPackageRecords_Check(op) PyObject_TypeCheck(op, &PyPackageRecords_Type) +# define PyPolicy_Check(op) PyObject_TypeCheck(op, &PyPolicy_Type) +# define PyProblemResolver_Check(op) PyObject_TypeCheck(op, &PyProblemResolver_Type) +# define PySourceList_Check(op) PyObject_TypeCheck(op, &PySourceList_Type) +# define PySourceRecords_Check(op) PyObject_TypeCheck(op, &PySourceRecords_Type) +# define PyTagFile_Check(op) PyObject_TypeCheck(op, &PyTagFile_Type) +# define PyTagSection_Check(op) PyObject_TypeCheck(op, &PyTagSection_Type) +# define PyVersion_Check(op) PyObject_TypeCheck(op, &PyVersion_Type) +// Exact check macros. +# define PyAcquire_CheckExact(op) (Py_TYPE(op) == &PyAcquire_Type) +# define PyAcquireFile_CheckExact(op) (Py_TYPE(op) == &PyAcquireFile_Type) +# define PyAcquireItem_CheckExact(op) (Py_TYPE(op) == &PyAcquireItem_Type) +# define PyActionGroup_CheckExact(op) (Py_TYPE(op) == &PyActionGroup_Type) +# define PyCache_CheckExact(op) (Py_TYPE(op) == &PyCache_Type) +# define PyCacheFile_CheckExact(op) (Py_TYPE(op) == &PyCacheFile_Type) +# define PyCdrom_CheckExact(op) (Py_TYPE(op) == &PyCdrom_Type) +# define PyConfiguration_CheckExact(op) (Py_TYPE(op) == &PyConfiguration_Type) +# define PyDepCache_CheckExact(op) (Py_TYPE(op) == &PyDepCache_Type) +# define PyDependency_CheckExact(op) (Py_TYPE(op) == &PyDependency_Type) +# define PyDependencyList_CheckExact(op) (Py_TYPE(op) == &PyDependencyList_Type) +# define PyDescription_CheckExact(op) (Py_TYPE(op) == &PyDescription_Type) +# define PyHashes_CheckExact(op) (Py_TYPE(op) == &PyHashes_Type) +# define PyHashString_CheckExact(op) (Py_TYPE(op) == &PyHashString_Type) +# define PyIndexRecords_CheckExact(op) (Py_TYPE(op) == &PyIndexRecords_Type) +# define PyMetaIndex_CheckExact(op) (Py_TYPE(op) == &PyMetaIndex_Type) +# define PyPackage_CheckExact(op) (Py_TYPE(op) == &PyPackage_Type) +# define PyPackageFile_CheckExact(op) (Py_TYPE(op) == &PyPackageFile_Type) +# define PyPackageIndexFile_CheckExact(op) (Py_TYPE(op) == &PyPackageIndexFile_Type) +# define PyPackageList_CheckExact(op) (Py_TYPE(op) == &PyPackageList_Type) +# define PyPackageManager_CheckExact(op) (Py_TYPE(op) == &PyPackageManager_Type) +# define PyPackageRecords_CheckExact(op) (Py_TYPE(op) == &PyPackageRecords_Type) +# define PyPolicy_CheckExact(op) (Py_TYPE(op) == &PyPolicy_Type) +# define PyProblemResolver_CheckExact(op) (Py_TYPE(op) == &PyProblemResolver_Type) +# define PySourceList_CheckExact(op) (Py_TYPE(op) == &PySourceList_Type) +# define PySourceRecords_CheckExact(op) (Py_TYPE(op) == &PySourceRecords_Type) +# define PyTagFile_CheckExact(op) (Py_TYPE(op) == &PyTagFile_Type) +# define PyTagSection_CheckExact(op) (Py_TYPE(op) == &PyTagSection_Type) +# define PyVersion_CheckExact(op) (Py_TYPE(op) == &PyVersion_Type) + +// Get the underlying C++ reference or pointer from the Python object. +# define PyAcquire_ToCpp GetCpp +# define PyAcquireFile_ToCpp GetCpp +# define PyAcquireItem_ToCpp GetCpp +# define PyActionGroup_ToCpp GetCpp +# define PyCache_ToCpp GetCpp +# define PyCacheFile_ToCpp GetCpp +# define PyCdrom_ToCpp GetCpp +# define PyConfiguration_ToCpp GetCpp +# define PyDepCache_ToCpp GetCpp +# define PyDependency_ToCpp GetCpp +//# define PyDependencyList_ToCpp GetCpp // NOT EXPORTED +# define PyDescription_ToCpp GetCpp +# define PyHashes_ToCpp GetCpp +# define PyHashString_ToCpp GetCpp +# define PyIndexRecords_ToCpp GetCpp +# define PyMetaIndex_ToCpp GetCpp +# define PyPackage_ToCpp GetCpp +# define PyPackageFile_ToCpp GetCpp +# define PyPackageIndexFile_ToCpp GetCpp +//# define PyPackageList_ToCpp GetCpp // NOT EXPORTED. +# define PyPackageManager_ToCpp GetCpp +//# define PyPackageRecords_ToCpp GetCpp // NOT EXPORTED +# define PyPolicy_ToCpp GetCpp +# define PyProblemResolver_ToCpp GetCpp +# define PySourceList_ToCpp GetCpp +//# define PySourceRecords_ToCpp GetCpp // NOT EXPORTED +# define PyTagFile_ToCpp GetCpp +# define PyTagSection_ToCpp GetCpp +# define PyVersion_ToCpp GetCpp + +// Python object creation, using two inline template functions and one variadic +// macro per type. +template +inline PyObject *FromCpp(PyTypeObject *pytype, Cpp obj, bool Delete=false) +{ + CppPyObject *Obj = CppPyObject_NEW(pytype, obj); + Obj->NoDelete = (!Delete); + return Obj; +} + +template +inline PyObject *FromCppOwned(PyTypeObject *pytype, Cpp const &obj, + bool Delete=false, PyObject *Owner=NULL) +{ + CppOwnedPyObject *Obj = CppOwnedPyObject_NEW(Owner, pytype, obj); + Obj->NoDelete = (!Delete); + return Obj; +} + +# define PyAcquire_FromCpp(...) FromCpp(&PyAcquire_Type, ##__VA_ARGS__) +# define PyAcquireFile_FromCpp(...) FromCppOwned(&PyAcquireFile_Type, ##__VA_ARGS__) +# define PyAcquireItem_FromCpp(...) FromCppOwned(&PyAcquireItemType,##__VA_ARGS__) +# define PyActionGroup_FromCpp(...) FromCppOwned(&PyActionGroup_Type,##__VA_ARGS__) +# define PyCache_FromCpp(...) FromCppOwned(&PyCache_Type,##__VA_ARGS__) +# define PyCacheFile_FromCpp(...) FromCpp(&PyCacheFile_Type,##__VA_ARGS__) +# define PyCdrom_FromCpp(...) FromCpp(&PyCdromType,##__VA_ARGS__) +# define PyConfiguration_FromCpp(...) FromCppOwned(&PyConfiguration_Type, ##__VA_ARGS__) +# define PyDepCache_FromCpp(...) FromCppOwned(&PyDepCache_Type,##__VA_ARGS__) +# define PyDependency_FromCpp(...) FromCppOwned(&PyDependency_Type,##__VA_ARGS__) +//# define PyDependencyList_FromCpp(...) FromCppOwned(&PyDependencyList_Type,##__VA_ARGS__) +# define PyDescription_FromCpp(...) FromCppOwned(&PyDescription_Type,##__VA_ARGS__) +# define PyHashes_FromCpp(...) FromCpp(&PyHashes_Type,##__VA_ARGS__) +# define PyHashString_FromCpp(...) FromCpp(&PyHashString_Type,##__VA_ARGS__) +# define PyIndexRecords_FromCpp(...) FromCpp(&PyIndexRecords_Type,##__VA_ARGS__) +# define PyMetaIndex_FromCpp(...) FromCppOwned(&PyMetaIndex_Type,##__VA_ARGS__) +# define PyPackage_FromCpp(...) FromCppOwned(&PyPackage_Type,##__VA_ARGS__) +# define PyPackageIndexFile_FromCpp(...) FromCppOwned(&PyPackageIndexFile_Type,##__VA_ARGS__) +# define PyPackageFile_FromCpp(...) FromCppOwned(&PyPackageFile_Type,##__VA_ARGS__) +//# define PyPackageList_FromCpp(...) FromCppOwned(&PyPackageList_Type,##__VA_ARGS__) +# define PyPackageManager_FromCpp(...) FromCpp(&PyPackageManagerType,##__VA_ARGS__) +//# define PyPackageRecords_FromCpp(...) FromCppOwned(&PyPackageRecords_Type,##__VA_ARGS__) +# define PyPolicy_FromCpp(...) FromCppOwned(&PyPolicy_Type,##__VA_ARGS__) +# define PyProblemResolver_FromCpp(...) FromCppOwned(&PyProblemResolver_Type,##__VA_ARGS__) +# define PySourceList_FromCpp(...) FromCpp(&PySourceList_Type,##__VA_ARGS__) +//# define PySourceRecords_FromCpp(...) FromCpp(&PySourceRecords_Type,##__VA_ARGS__) +//# define PyTagFile_FromCpp(...) FromCppOwned(&PyTagFile_Type,##__VA_ARGS__) +# define PyTagSection_FromCpp(...) FromCppOwned(&PyTagSection_Type,##__VA_ARGS__) +# define PyVersion_FromCpp(...) FromCppOwned(&PyVersion_Type,##__VA_ARGS__) +#endif -- cgit v1.2.3 From acf567325e793ab37292c21e6b4c0713d92ee9a1 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 14:32:40 +0200 Subject: Upgrade to debhelper 7 and remove debian/tmp in python-apt.install, to work around a bug in debhelper. --- debian/changelog | 2 ++ debian/compat | 2 +- debian/control | 2 +- debian/python-apt.install | 6 +++--- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 415ebdd2..8c1b0e67 100644 --- a/debian/changelog +++ b/debian/changelog @@ -35,6 +35,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Make AcquireItem objects raise ValueError instead of segfaulting when the Acquire() object is shut down or the main object (e.g. AcquireFile) is deallocated. * Unify all Configuration,ConfigurationPtr,ConfigurationSub into one type. + * Upgrade to debhelper 7 and remove debian/tmp in python-apt.install, to + work around a bug in debhelper. [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/debian/compat b/debian/compat index 7ed6ff82..7f8f011e 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -5 +7 diff --git a/debian/control b/debian/control index a16ae10e..78c55126 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ Standards-Version: 3.8.2 XS-Python-Version: all Build-Depends: apt-utils, cdbs, - debhelper (>= 5.0.37.1), + debhelper (>= 7), libapt-pkg-dev (>= 0.7.22~), python-all-dbg, python-all-dev, diff --git a/debian/python-apt.install b/debian/python-apt.install index 4910e8ed..efd54743 100644 --- a/debian/python-apt.install +++ b/debian/python-apt.install @@ -1,3 +1,3 @@ -debian/tmp/usr/lib/python* -debian/tmp/usr/share/locale -debian/tmp/usr/share/python-apt +usr/lib/python* +usr/share/locale +usr/share/python-apt -- cgit v1.2.3 From 270a8f2e01e6f961e7501f3cefb64d2bf8f70069 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 14:58:35 +0200 Subject: Build-Depend on python-all-dev (>= 2.5.4-3), so we build for Python 2.6 --- debian/changelog | 3 ++- debian/control | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 8c1b0e67..70157470 100644 --- a/debian/changelog +++ b/debian/changelog @@ -37,6 +37,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Unify all Configuration,ConfigurationPtr,ConfigurationSub into one type. * Upgrade to debhelper 7 and remove debian/tmp in python-apt.install, to work around a bug in debhelper. + * Build-Depend on python-all-dev (>= 2.5.4-3), so we build for Python 2.6 [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message @@ -52,7 +53,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * python/progress.cc: - low level code for update_status_full and pulse_items() - -- Julian Andres Klode Tue, 14 Jul 2009 20:42:03 +0200 + -- Julian Andres Klode Wed, 15 Jul 2009 14:56:24 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/debian/control b/debian/control index 78c55126..897ef3de 100644 --- a/debian/control +++ b/debian/control @@ -9,8 +9,8 @@ Build-Depends: apt-utils, cdbs, debhelper (>= 7), libapt-pkg-dev (>= 0.7.22~), - python-all-dbg, - python-all-dev, + python-all-dbg (>= 2.5.4-3), + python-all-dev (>= 2.5.4-3), python3.1-dev, python3.1-dbg, python-central (>= 0.5), -- cgit v1.2.3 From 57ce95170dc181c26633036f7c2adfd1c83192bf Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 15:21:38 +0200 Subject: debian/rules: Add --install-layout=deb, debian/control: XS-Python-Version >= 2.5 --- debian/control | 2 +- debian/rules | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 897ef3de..9e0fe3ea 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: APT Development Team Uploaders: Michael Vogt , Julian Andres Klode Standards-Version: 3.8.2 -XS-Python-Version: all +XS-Python-Version: >= 2.5 Build-Depends: apt-utils, cdbs, debhelper (>= 7), diff --git a/debian/rules b/debian/rules index 7a6ff690..f9b08384 100755 --- a/debian/rules +++ b/debian/rules @@ -17,10 +17,11 @@ PY3K_VERSIONS := $(shell find /usr/bin/python3.? | sed s/.*python//) PKG=python-apt DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv +DEB_PYTHON_INSTALL_ARGS_ALL=--no-compile --install-layout=deb DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS) # Define COMPAT_0_7 to get all the deprecated interfaces. -export CFLAGS+=-DCOMPAT_0_7 +export CFLAGS+=-DCOMPAT_0_7 -Wno-write-strings export DEBVER build/python-apt:: -- cgit v1.2.3 From 7581c5fb8a8d8e1e0a79c343cbd23725475f846c Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 17:02:34 +0200 Subject: Simplify the whole building, build all Python versions with setup.py --- debian/changelog | 1 + debian/control | 4 +-- debian/python-apt.doc-base | 3 -- debian/python-apt.docs | 3 +- debian/rules | 35 +++------------------ po/python-apt.pot | 2 +- python/makefile | 27 ---------------- setup.py | 73 ++++++++++++++++++++----------------------- setup3.py | 77 ---------------------------------------------- 9 files changed, 43 insertions(+), 182 deletions(-) delete mode 100644 python/makefile mode change 100755 => 100644 setup.py delete mode 100644 setup3.py (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 70157470..5e3ec667 100644 --- a/debian/changelog +++ b/debian/changelog @@ -38,6 +38,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Upgrade to debhelper 7 and remove debian/tmp in python-apt.install, to work around a bug in debhelper. * Build-Depend on python-all-dev (>= 2.5.4-3), so we build for Python 2.6 + * Simplify the whole building, build all Python versions with setup.py [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/debian/control b/debian/control index 9e0fe3ea..36a4d8d8 100644 --- a/debian/control +++ b/debian/control @@ -8,13 +8,13 @@ XS-Python-Version: >= 2.5 Build-Depends: apt-utils, cdbs, debhelper (>= 7), - libapt-pkg-dev (>= 0.7.22~), + libapt-pkg-dev (>= 0.7.12~), python-all-dbg (>= 2.5.4-3), python-all-dev (>= 2.5.4-3), python3.1-dev, python3.1-dbg, python-central (>= 0.5), - python-distutils-extra (>= 1.9.0), + python-distutils-extra (>= 2.0), python-gtk2, python-sphinx (>= 0.5), python-vte diff --git a/debian/python-apt.doc-base b/debian/python-apt.doc-base index d25926b7..e9b2040c 100644 --- a/debian/python-apt.doc-base +++ b/debian/python-apt.doc-base @@ -6,6 +6,3 @@ Section: Programming/Python Format: HTML Index: /usr/share/doc/python-apt/html/index.html Files: /usr/share/doc/python-apt/html/* - -Format: Text -Files: /usr/share/doc/python-apt/text/* diff --git a/debian/python-apt.docs b/debian/python-apt.docs index 6ba083f5..29219341 100644 --- a/debian/python-apt.docs +++ b/debian/python-apt.docs @@ -1,5 +1,4 @@ README apt/README.apt data/templates/README.templates -build/doc/html/ -build/doc/text/ +build/sphinx/html/ diff --git a/debian/rules b/debian/rules index f9b08384..967da911 100755 --- a/debian/rules +++ b/debian/rules @@ -11,56 +11,29 @@ DEB_PYTHON_PACKAGES_EXCLUDE=python-apt-dbg include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/python-distutils.mk -PY3K_VERSIONS := $(shell find /usr/bin/python3.? | sed s/.*python//) -2TO3_VERSION := $(lastword $(PY3K_VERSIONS)) +# Add python3 versions to the list of python versions +cdbs_python_build_versions += $(shell find /usr/bin/python3.? | sed s/.*python//) + -PKG=python-apt DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv DEB_PYTHON_INSTALL_ARGS_ALL=--no-compile --install-layout=deb -DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS) # Define COMPAT_0_7 to get all the deprecated interfaces. export CFLAGS+=-DCOMPAT_0_7 -Wno-write-strings export DEBVER -build/python-apt:: - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i setup3.py build; \ - done - -install/python-apt:: - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i ./setup3.py install --root $(CURDIR)/debian/python-apt \ - --install-layout=deb --no-compile; \ - done - -ifneq ($(PY3K_VERSIONS),) - find $(CURDIR)/debian/python-apt/usr/lib/python3*/dist-packages/ -name '*.py' \ - | xargs 2to3-$(2TO3_VERSION)| patch -p0 -endif - build/python-apt-dbg:: set -e; \ for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py build; \ done - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i-dbg setup3.py build; \ - done - install/python-apt-dbg:: for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py install --root $(CURDIR)/debian/python-apt-dbg \ - --no-compile; \ + $(DEB_PYTHON_INSTALL_ARGS_ALL); \ done - - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i-dbg ./setup3.py install --root $(CURDIR)/debian/python-apt-dbg \ - --install-layout=deb --no-compile; \ - done - find debian/python-apt-dbg \ ! -type d ! -name '*_d.so' | xargs rm -f find debian/python-apt-dbg -depth -empty -exec rmdir {} \; diff --git a/po/python-apt.pot b/po/python-apt.pot index 3f4fbb6b..3becb5e1 100644 --- a/po/python-apt.pot +++ b/po/python-apt.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-07-15 15:17+0200\n" +"POT-Creation-Date: 2009-07-15 16:51+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/python/makefile b/python/makefile deleted file mode 100644 index fff3a2e8..00000000 --- a/python/makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -*- make -*- -BASE=.. -SUBDIR=python - -# Bring in the default rules -include ../buildlib/defaults.mak - -# The apt_pkg module -MODULE=apt_pkg -SLIBS = -lapt-pkg -LIB_MAKES = apt-pkg/makefile -APT_PKG_SRC = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \ - cache.cc pkgrecords.cc pkgsrcrecords.cc sourcelist.cc \ - depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \ - indexfile.cc metaindex.cc hashstring.cc indexrecords.cc \ - policy.cc hashes.cc -SOURCE := $(APT_PKG_SRC) -include $(PYTHON_H) progress.h - -# The apt_int module.. -MODULE=apt_inst -SLIBS = -lapt-inst -lapt-pkg -LIB_MAKES = apt-inst/makefile -APT_INST_SRC = apt_instmodule.cc tar.cc generic.cc -SOURCE := $(APT_INST_SRC) -include $(PYTHON_H) - diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 85f4c889..77853a4e --- a/setup.py +++ b/setup.py @@ -1,50 +1,59 @@ -#! /usr/bin/env python +#!/usr/bin/python +# Builds on python2.X and python3 # $Id: setup.py,v 1.2 2002/01/08 07:13:21 jgg Exp $ import glob import os -import shutil import sys from distutils.core import setup, Extension -from distutils.sysconfig import parse_makefile -from DistUtilsExtra.command import build_extra, build_i18n +cmdclass = {} +try: + from DistUtilsExtra.command import build_extra, build_i18n + from DistUtilsExtra.auto import clean_build_tree + cmdclass['build'] = build_extra.build_extra + cmdclass['build_i18n'] = build_i18n.build_i18n + cmdclass['clean'] = clean_build_tree + build_extra.build_extra.sub_commands.append(("build_sphinx", + lambda x: 'build_sphinx' in cmdclass)) +except ImportError: + print('W: [python%s] DistUtilsExtra import error.' % sys.version[:3]) -# The apt_pkg module -files = map(lambda source: "python/"+source, - sorted(parse_makefile("python/makefile")["APT_PKG_SRC"].split())) +try: + from sphinx.setup_command import BuildDoc + cmdclass['build_sphinx'] = BuildDoc +except ImportError: + print('W: [python%s] Sphinx import error.' % sys.version[:3]) + +if sys.version_info[0] == 3: + from distutils.command.build_py import build_py_2to3 + cmdclass['build_py'] = build_py_2to3 + +# The apt_pkg module. +files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', + 'configuration.c', 'depcache.cc', 'generic.cc', 'hashes.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'] +files = ['python/' + fname for fname in files] apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module -files = map(lambda source: "python/"+source, - sorted(parse_makefile("python/makefile")["APT_INST_SRC"].split())) +files = ["python/apt_instmodule.cc", "python/generic.cc", "python/tar.cc"] apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) # Replace the leading _ that is used in the templates for translation -templates = [] - -# build doc if len(sys.argv) > 1 and sys.argv[1] == "build": if not os.path.exists("build/data/templates/"): os.makedirs("build/data/templates") for template in glob.glob('data/templates/*.info.in'): source = open(template, "r") - build = open(os.path.join("build", template[:-3]), "w") - lines = source.readlines() - for line in lines: + build = open("build/" + template[:-3], "w") + for line in source: build.write(line.lstrip("_")) source.close() build.close() - -if len(sys.argv) > 1 and sys.argv[1] == "clean" and '-a' in sys.argv: - for dirname in "build/doc", "doc/build", "build/data", "build/mo": - if os.path.exists(dirname): - print "Removing", dirname - shutil.rmtree(dirname) - else: - print "Not removing", dirname, "because it does not exist" - setup(name="python-apt", description="Python bindings for APT", version=os.environ.get('DEBVER'), @@ -56,20 +65,6 @@ setup(name="python-apt", glob.glob('build/data/templates/*.info')), ('share/python-apt/templates', glob.glob('data/templates/*.mirrors'))], - cmdclass = {"build": build_extra.build_extra, - "build_i18n": build_i18n.build_i18n}, + cmdclass = cmdclass, license = 'GNU GPL', platforms = 'posix') - -if len(sys.argv) > 1 and sys.argv[1] == "build": - import sphinx - try: - import pygtk - except ImportError: - print >> sys.stderr, ('W: Not building documentation because python-' - 'gtk2 is not available at the moment.') - sys.exit(0) - sphinx.main(["sphinx", "-b", "html", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/html"]) - sphinx.main(["sphinx", "-b", "text", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/text"]) diff --git a/setup3.py b/setup3.py deleted file mode 100644 index a3cbdc8e..00000000 --- a/setup3.py +++ /dev/null @@ -1,77 +0,0 @@ -#! /usr/bin/env python3 -# $Id: setup.py,v 1.2 2002/01/08 07:13:21 jgg Exp $ -import glob -import os -import shutil -import sys - -from distutils.core import setup, Extension -from distutils.sysconfig import parse_makefile -#from DistUtilsExtra.command import build_extra, build_i18n - - -# The apt_pkg module -files = ["python/"+source for source in parse_makefile("python/makefile")["APT_PKG_SRC"].split()] -apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) - -# The apt_inst module -files = ["python/"+source for source in parse_makefile("python/makefile")["APT_INST_SRC"].split()] -apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) - -# Replace the leading _ that is used in the templates for translation -templates = [] - -# build doc -if len(sys.argv) > 1 and sys.argv[1] == "build": - if not os.path.exists("build/data/templates/"): - os.makedirs("build/data/templates") - for template in glob.glob('data/templates/*.info.in'): - source = open(template, "r") - build = open(os.path.join("build", template[:-3]), "w") - lines = source.readlines() - for line in lines: - build.write(line.lstrip("_")) - source.close() - build.close() - - -if len(sys.argv) > 1 and sys.argv[1] == "clean" and '-a' in sys.argv: - for dirname in "build/doc", "doc/build", "build/data", "build/mo": - if os.path.exists(dirname): - print("Removing", dirname) - shutil.rmtree(dirname) - else: - print("Not removing", dirname, "because it does not exist") - -setup(name="python-apt", - description="Python bindings for APT", - version=os.environ.get('DEBVER'), - author="APT Development Team", - author_email="deity@lists.debian.org", - ext_modules=[apt_pkg, apt_inst], - packages=['apt', 'apt.progress', 'aptsources'], - data_files = [('share/python-apt/templates', - glob.glob('build/data/templates/*.info')), - ('share/python-apt/templates', - glob.glob('data/templates/*.mirrors'))], -# cmdclass = {"build": build_extra.build_extra, -# "build_i18n": build_i18n.build_i18n}, - license = 'GNU GPL', - platforms = 'posix') - -if len(sys.argv) > 1 and sys.argv[1] == "build": - try: - import sphinx - except ImportError: - print(('W: Sphinx not available - Not building' - 'documentation'), file=sys.stderr) - try: - import pygtk - except ImportError: - print(('W: Not building documentation because python-' - 'gtk2 is not available at the moment.'), file=sys.stderr) - sys.exit(0) - sphinx.main(["sphinx", "-b", "html", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/html"]) - sphinx.main(["sphinx", "-b", "text", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/text"]) -- cgit v1.2.3 From aaf5907863bed9a044fa0e3e2eacd1ca2de53c59 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 21:36:58 +0200 Subject: Introduce new progress (base) classes in apt_pkg: - apt_pkg.AcquireProgress - apt_pkg.OpProgress --- debian/changelog | 3 + python/acquireprogress.cc | 198 ++++++++++++++++++++++++++++++++++++++++++++++ python/apt_pkgmodule.cc | 2 + python/apt_pkgmodule.h | 2 + python/opprogress.cc | 173 ++++++++++++++++++++++++++++++++++++++++ python/progress.cc | 14 +++- setup.py | 5 +- 7 files changed, 393 insertions(+), 4 deletions(-) create mode 100644 python/acquireprogress.cc create mode 100644 python/opprogress.cc (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 5e3ec667..b2936ba1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -39,6 +39,9 @@ python-apt (0.7.92) UNRELEASED; urgency=low work around a bug in debhelper. * Build-Depend on python-all-dev (>= 2.5.4-3), so we build for Python 2.6 * Simplify the whole building, build all Python versions with setup.py + * Introduce new progress (base) classes in apt_pkg: + - apt_pkg.AcquireProgress + - apt_pkg.OpProgress [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/python/acquireprogress.cc b/python/acquireprogress.cc new file mode 100644 index 00000000..ac3b8fd9 --- /dev/null +++ b/python/acquireprogress.cc @@ -0,0 +1,198 @@ +/* acquireprogress.cc - Base class for FetchProgress classes. + * + * Copyright 2009 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 "generic.h" +#include +#include + +typedef struct { + PyObject_HEAD + double last_bytes; + double current_cps; + double current_bytes; + double total_bytes; + double fetched_bytes; + unsigned long elapsed_time; + unsigned long total_items; + unsigned long current_items; +} PyAcquireProgressObject; + + +// DUMMY IMPLEMENTATIONS. +static char *acquireprogress_media_change_doc = + "media_change(media: str, drive: str) -> bool\n\n" + "Invoked when the user should be prompted to change the inserted\n" + "removable media.\n\n" + "This method should not return until the user has confirmed to the user\n" + "interface that the media change is complete.\n\n" + ":param:media The name of the media type that should be changed.\n" + ":param:drive The identifying name of the drive whose media should be\n" + " changed.\n\n" + "Return True if the user confirms the media change, False if it is\n" + "cancelled."; +static PyObject *acquireprogress_media_change(PyObject *self, PyObject *args) +{ + Py_RETURN_FALSE; +} + +static char *acquireprogress_ims_hit_doc = "ims_hit(item: AcquireItemDesc)\n\n" + "Invoked when an item is confirmed to be up-to-date. For instance,\n" + "when an HTTP download is informed that the file on the server was\n" + "not modified."; +static PyObject *acquireprogress_ims_hit(PyObject *self, PyObject *arg) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_fetch_doc = "fetch(item: AcquireItemDesc)\n\n" + "Invoked when some of an item's data is fetched."; +static PyObject *acquireprogress_fetch(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_done_doc = "done(item: AcquireItemDesc)\n\n" + "Invoked when an item is successfully and completely fetched."; +static PyObject *acquireprogress_done(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_fail_doc = "fail(item: AcquireItemDesc)\n\n" + "Invoked when the process of fetching an item encounters a fatal error."; +static PyObject *acquireprogress_fail(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_pulse_doc = "pulse(owner: Acquire) -> bool\n\n" + "Periodically invoked while the Acquire process is underway.\n\n" + "Return False if the user asked to cancel the whole Acquire process."; +static PyObject *acquireprogress_pulse(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_TRUE; +} + +static char *acquireprogress_start_doc = "start()\n\n" + "Invoked when the Acquire process starts running."; +static PyObject *acquireprogress_start(PyObject *self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static char *acquireprogress_stop_doc = "stop()\n\n" + "Invoked when the Acquire process stops running."; +static PyObject *acquireprogress_stop(PyObject *self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static PyMethodDef acquireprogress_methods[] = { + {"media_change", acquireprogress_media_change, METH_VARARGS, + acquireprogress_media_change_doc}, + {"ims_hit",acquireprogress_ims_hit,METH_VARARGS, + acquireprogress_ims_hit_doc}, + {"fetch",acquireprogress_fetch,METH_VARARGS,acquireprogress_fetch_doc}, + {"done",acquireprogress_done,METH_VARARGS,acquireprogress_done_doc}, + {"fail",acquireprogress_fail,METH_VARARGS,acquireprogress_fail_doc}, + {"pulse",acquireprogress_pulse,METH_VARARGS,acquireprogress_pulse_doc}, + {"start",acquireprogress_start,METH_NOARGS,acquireprogress_start_doc}, + {"stop",acquireprogress_stop,METH_NOARGS,acquireprogress_stop_doc}, + {NULL} +}; + +static PyMemberDef acquireprogress_members[] = { + {"last_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, last_bytes), 0, + "The number of bytes fetched as of the previous call to pulse(),\n" + "including local items."}, + {"current_cps", T_DOUBLE, offsetof(PyAcquireProgressObject, current_cps), 0, + "The current rate of download, in bytes per second."}, + {"current_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, current_bytes), + 0, "The number of bytes fetched."}, + {"total_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, total_bytes), 0, + "The total number of bytes that need to be fetched. This member is\n" + "inaccurate, as new items might be enqueued while the download is\n" + "in progress!"}, + {"fetched_bytes", T_DOUBLE,offsetof(PyAcquireProgressObject, fetched_bytes), + 0, "The total number of bytes accounted for by items that were\n" + "successfully fetched."}, + {"elapsed_time", T_ULONG, offsetof(PyAcquireProgressObject, elapsed_time),0, + "The amount of time that has elapsed since the download started."}, + {"total_items", T_ULONG, offsetof(PyAcquireProgressObject, total_items),0, + "The total number of items that need to be fetched. This member is\n" + "inaccurate, as new items might be enqueued while the download is\n" + "in progress!"}, + {"current_items", T_ULONG, offsetof(PyAcquireProgressObject, current_items), + 0, "The number of items that have been successfully downloaded."}, + {NULL} +}; + +static char *acquireprogress_doc = "AcquireProgress()\n\n" + "A monitor object for downloads controlled by the Acquire class. This is\n" + "an mostly abstract class. You should subclass it and implement the\n" + "methods to get something useful."; + +PyTypeObject PyAcquireProgress_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireProgress", // tp_name + sizeof(PyAcquireProgressObject), // tp_basicsize + 0, // tp_itemsize + // Methods + 0, // 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, + acquireprogress_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + acquireprogress_methods, // tp_methods + acquireprogress_members, // 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 + PyType_GenericNew, // tp_new +}; diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index bc2f4258..4f948847 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -621,6 +621,8 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"HashString",&PyHashString_Type); ADDTYPE(Module,"Policy",&PyPolicy_Type); ADDTYPE(Module,"Hashes",&PyHashes_Type); + ADDTYPE(Module,"OpProgress",&PyOpProgress_Type); + ADDTYPE(Module,"AcquireProgress",&PyAcquireProgress_Type); // Tag file constants PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", CharCharToList(TFRewritePackageOrder)); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 97be5d5c..34bc2ae5 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -112,6 +112,8 @@ extern PyTypeObject PyIndexRecords_Type; // Policy extern PyTypeObject PyPolicy_Type; extern PyTypeObject PyHashes_Type; +extern PyTypeObject PyOpProgress_Type; +extern PyTypeObject PyAcquireProgress_Type; #include "python-apt.h" #endif diff --git a/python/opprogress.cc b/python/opprogress.cc new file mode 100644 index 00000000..450e290a --- /dev/null +++ b/python/opprogress.cc @@ -0,0 +1,173 @@ +/* op-progress.cc - Base class for OpProgress classes. + * + * Copyright 2009 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 "generic.h" +#include +#include + +typedef struct { + PyObject_HEAD + PyObject *op; + PyObject *subop; + int major_change; + float percent; +} PyOpProgressObject; + +static PyObject *opprogress_update(PyObject *Self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static PyObject *opprogress_done(PyObject *Self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static PyObject *opprogress_get_op(PyOpProgressObject *self, void *closure) +{ + return self->op; +} + +static int opprogress_set_op(PyOpProgressObject *self, PyObject *value, + void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'op'"); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError,"'op' must be a string."); + return -1; + } + Py_DECREF(self->op); + Py_INCREF(value); + + self->op = value; + return 0; +} + +static PyObject *opprogress_get_subop(PyOpProgressObject *self, void *closure) +{ + return self->subop; +} + +static int opprogress_set_subop(PyOpProgressObject *self, PyObject *value, + void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'subop'."); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError,"'subop' must be a string."); + return -1; + } + Py_DECREF(self->subop); + Py_INCREF(value); + self->subop = value; + return 0; +} + +static PyMethodDef opprogress_methods[] = { + {"update",opprogress_update,METH_NOARGS,"update()\n\nCalled periodically."}, + {"done",opprogress_done,METH_NOARGS,"update()\n\nCalled when done."}, + {NULL}, +}; + +static PyMemberDef opprogress_members[] = { + {"major_change", T_INT, offsetof(PyOpProgressObject, major_change), 0, + "Boolean value indicating whether the change is a major change."}, + {"percent", T_FLOAT, offsetof(PyOpProgressObject, percent), 0, + "Percentage of completion (float value)."}, + {NULL} +}; + +static PyGetSetDef opprogress_getset[] = { + {"op", (getter)opprogress_get_op, (setter)opprogress_set_op, + "Description of the current operation"}, + {"subop", (getter)opprogress_get_subop, (setter)opprogress_set_subop, + "Description of the current sub-operation"}, + {NULL}, +}; + +static void opprogress_dealloc(PyObject *self) +{ + Py_XDECREF(((PyOpProgressObject *)self)->op); + Py_XDECREF(((PyOpProgressObject *)self)->subop); + self->ob_type->tp_free(self); +} + +static PyObject *opprogress_new(PyTypeObject *type, PyObject *args, + PyObject *kwds) +{ + PyOpProgressObject *res = (PyOpProgressObject *)type->tp_alloc(type, 0); + res->op = PyString_FromString(""); + res->subop = PyString_FromString(""); + return (PyObject *)res; +} + +static char *opprogress_doc = "OpProgress()\n\n" + "A base class for writing custom operation progress classes. Subclasses\n" + "should override all the methods (and call the parent ones) but shall\n" + "not override any of the inherited descriptors because they may be\n" + "ignored."; + +PyTypeObject PyOpProgress_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.OpProgress", // tp_name + sizeof(PyOpProgressObject), // tp_basicsize + 0, // tp_itemsize + // Methods + opprogress_dealloc, // 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, + opprogress_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + opprogress_methods, // tp_methods + opprogress_members, // tp_members + opprogress_getset, // 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 + opprogress_new, // tp_new +}; diff --git a/python/progress.cc b/python/progress.cc index 44f27b0c..b1845f0a 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -15,6 +15,7 @@ #include #include "progress.h" #include "generic.h" +#include "apt_pkgmodule.h" // generic bool PyCallbackObj::RunSimpleCallback(const char* method_name, @@ -75,11 +76,20 @@ void PyOpProgress::Update() PyObject_SetAttrString(callbackInst, "majorChange", o); Py_XDECREF(o); + + // Build up the argument list... if(CheckChange(0.05)) { - PyObject *arglist = Py_BuildValue("(f)", Percent); - RunSimpleCallback("update", arglist); + if (PyObject_TypeCheck(callbackInst, &PyOpProgress_Type)) { + o = Py_BuildValue("f", Percent); + PyObject_SetAttrString(callbackInst, "percent", o); + RunSimpleCallback("update"); + Py_XDECREF(o); + } else { + PyObject *arglist = Py_BuildValue("(f)", Percent); + RunSimpleCallback("update", arglist); + } } }; diff --git a/setup.py b/setup.py index af373632..b6dde3f9 100644 --- a/setup.py +++ b/setup.py @@ -34,8 +34,9 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'configuration.cc', 'depcache.cc', 'generic.cc', 'hashes.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'] -files = ['python/' + fname for fname in files] + 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', + 'opprogress.cc', 'acquireprogress.cc'] +files = sorted(['python/' + fname for fname in files]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module -- cgit v1.2.3 From 4112520954a16ebbfdf7511670e68668e5a07173 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 30 Jul 2009 20:38:03 +0200 Subject: debian/control: Add 3.1 to XS-Python-Version. --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 7c3bfaac..9a8d16a2 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: APT Development Team Uploaders: Michael Vogt , Julian Andres Klode Standards-Version: 3.8.2 -XS-Python-Version: >= 2.5 +XS-Python-Version: >= 2.5, 3.1 Build-Depends: apt-utils, debhelper (>= 7.3.5), libapt-pkg-dev (>= 0.7.22~), -- cgit v1.2.3 From 7c19d9450b549180a6f0071f1d980dcf360c8921 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 30 Jul 2009 20:38:59 +0200 Subject: debian/rules: Add -DCOMPAT_0_7 to the CFLAGS again. --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/rules b/debian/rules index 6e2204cf..d5ebe29d 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,7 @@ #!/usr/bin/make -f export DH_PYCENTRAL=nomove export DEBVER=$(shell dpkg-parsechangelog | sed -n -e 's/^Version: //p') -export CFLAGS=-Wno-write-strings +export CFLAGS=-Wno-write-strings -DCOMPAT_0_7 %: dh --with python-central $@ -- cgit v1.2.3 From ebe1f37a65cae8303bf86da13f3f2107cd73d1fe Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 30 Jul 2009 20:59:49 +0200 Subject: debian/control: Explicitly specify the versions to build for. --- debian/control | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 9a8d16a2..69bca37a 100644 --- a/debian/control +++ b/debian/control @@ -4,12 +4,14 @@ Priority: optional Maintainer: APT Development Team Uploaders: Michael Vogt , Julian Andres Klode Standards-Version: 3.8.2 -XS-Python-Version: >= 2.5, 3.1 +XS-Python-Version: 2.5, 2.6, 3.1 Build-Depends: apt-utils, debhelper (>= 7.3.5), libapt-pkg-dev (>= 0.7.22~), - python-all-dbg (>= 2.5.4-3), - python-all-dev (>= 2.5.4-3), + python2.5-dbg, + python2.5-dev, + python2.6-dev, + python2.6-dbg, python3.1-dev, python3.1-dbg, python-central (>= 0.5), -- cgit v1.2.3 From 98e0bc92e8aad896fd9a56159f6a5ca002287f3b Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 31 Jul 2009 21:00:04 +0200 Subject: debian/changelog: Rework latest changelog block to be more readable. --- debian/changelog | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index ce5c3b22..d07433fd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,17 +1,17 @@ python-apt (0.7.92) UNRELEASED; urgency=low - * Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141) - * Add apt_pkg.Policy class (Closes: #382725) - * Provide a C++ API in the package python-apt-dev (Closes: #334923) - * Allow types providing __new__() to be subclassed. - * Bugfix: Delete pointers correctly, fixing memory leaks. (LP: #370149) - * Add apt_pkg.DepCache.mark_auto() and apt.Package.mark_auto() methods to - mark a package as automatically installed. - * Drop apt_pkg.Cache.open() and apt_pkg.Cache.close(), they cause segfaults - and memory leaks. Simply create a new cache instxead. - * Merge releases 0.7.10.4 - 0.7.12.0 from unstable - * Make AcquireFile a subclass of AcquireItem - * Make ConfigurationPtr,ConfigurationSub subclasses of Configuration. + * New features: + - Provide a C++ API in the package python-apt-dev (Closes: #334923). + - Add apt_pkg.HashString and apt_pkg.IndexRecords (Closes: #456141). + - Add apt_pkg.Policy class (Closes: #382725). + - Add apt_pkg.Hashes class. + - Allow types providing __new__() to be subclassed. + - Add apt_pkg.DepCache.mark_auto() and apt.Package.mark_auto() methods to + mark a package as automatically installed. + - Make AcquireFile a subclass of AcquireItem, thus inheriting attributes. + - New progress handling in apt.progress.base and apt.progress.text. Still + missing Qt4 progress handlers. + * Unification of dependency handling: - apt_pkg.parse_[src_]depends() now use CompType instead of CompTypeDeb (i.e. < instead of <<) to match the interface of Version.depends_list_str @@ -20,15 +20,17 @@ python-apt (0.7.92) UNRELEASED; urgency=low + Closes: #468123 - there is no need anymore for binding CompType or CompTypeDeb, because we don't return integer values for CompType anymore. - * Introduce apt_pkg.Hashes class. - * Make AcquireItem objects raise ValueError instead of segfaulting when the Acquire() - object is shut down or the main object (e.g. AcquireFile) is deallocated. - * Unify all Configuration,ConfigurationPtr,ConfigurationSub into one type. - * Build-Depend on python-all-dev (>= 2.5.4-3), so we build for Python 2.6 - * Simplify the whole building, build all Python versions with setup.py - * Introduce new progress (base) classes in apt_pkg: - - apt_pkg.AcquireProgress - - apt_pkg.OpProgress + + * Bugfixes: + - Delete pointers correctly, fixing memory leaks (LP: #370149). + - Drop open() and close() in apt_pkg.Cache as they cause segfaults. + - Raise ValueError in AcquireItem if the Acquire process is shut down + instead of segfaulting. + + * Other stuff: + - Merge releases 0.7.10.4 - 0.7.12.0 from unstable. + - Merge Configuration,ConfigurationPtr,ConfigurationSub into one type. + - Simplify the whole build process by using a single setup.py. -- Julian Andres Klode Wed, 15 Jul 2009 14:56:24 +0200 -- cgit v1.2.3 From 992629cbd46b9cf830b8ab95e30f56bbcab4d724 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 31 Jul 2009 21:01:57 +0200 Subject: debian/changelog: Add note about documentation updates. --- debian/changelog | 1 + 1 file changed, 1 insertion(+) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index d07433fd..928493ad 100644 --- a/debian/changelog +++ b/debian/changelog @@ -31,6 +31,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low - Merge releases 0.7.10.4 - 0.7.12.0 from unstable. - Merge Configuration,ConfigurationPtr,ConfigurationSub into one type. - Simplify the whole build process by using a single setup.py. + - The documentation has been restructured and enhanced with tutorials. -- Julian Andres Klode Wed, 15 Jul 2009 14:56:24 +0200 -- cgit v1.2.3 From 08674e660118758f32d220a26b4a525459317293 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 2 Aug 2009 18:23:28 +0200 Subject: Only recommend lsb-release instead of depending on it. Default to Debian unstable if lsb_release is not available. --- aptsources/distinfo.py | 13 +++++++++---- aptsources/distro.py | 25 +++++++++++++++++++------ debian/changelog | 4 +++- debian/control | 4 ++-- 4 files changed, 33 insertions(+), 13 deletions(-) (limited to 'debian') diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py index 2e5fd7bc..0614bd1c 100644 --- a/aptsources/distinfo.py +++ b/aptsources/distinfo.py @@ -21,9 +21,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA +import errno import os import gettext from os import getenv +from subprocess import Popen, PIPE import ConfigParser import re @@ -160,10 +162,13 @@ class DistInfo: #match_mirror_line = re.compile(r".+") if not dist: - pipe = os.popen("lsb_release -i -s") - dist = pipe.read().strip() - pipe.close() - del pipe + try: + dist = Popen(["lsb_release", "-i", "-s"], + stdout=PIPE).communicate()[0].strip() + except OSError, exc: + if exc.errno != errno.ENOENT: + print 'WARNING: lsb_release failed, using defaults:', exc + dist = "Debian" self.dist = dist diff --git a/aptsources/distro.py b/aptsources/distro.py index 5398d4a3..2cbad9fb 100644 --- a/aptsources/distro.py +++ b/aptsources/distro.py @@ -437,6 +437,20 @@ class UbuntuDistribution(Distribution): Distribution.get_mirrors( self, mirror_template="http://%s.archive.ubuntu.com/ubuntu/") +def _lsb_release(): + """Call lsb_release --all and return a mapping.""" + from subprocess import Popen, PIPE + import errno + result = {'Codename': 'sid', 'Distributor ID': 'Debian', + 'Description': 'Debian GNU/Linux unstable (sid)', + 'Release': 'unstable'} + try: + out = Popen(['lsb_release', '--all'], stdout=PIPE).communicate()[0] + result.update(l.split(":\t") for l in out.split("\n") if ':\t' in l) + except OSError, exc: + if exc.errno != errno.ENOENT: + print 'WARNING: lsb_release failed, using defaults:', exc + return result def get_distro(id=None, codename=None, description=None, release=None): """ @@ -448,12 +462,11 @@ def get_distro(id=None, codename=None, description=None, release=None): """ # make testing easier if not (id and codename and description and release): - lsb_info = [] - for lsb_option in ["-i", "-c", "-d", "-r"]: - pipe = os.popen("lsb_release %s -s" % lsb_option) - lsb_info.append(pipe.read().strip()) - del pipe - (id, codename, description, release) = lsb_info + result = _lsb_release() + id = result['Distributor ID'] + codename = result['Codename'] + description = result['Description'] + release = result['Release'] if id == "Ubuntu": return UbuntuDistribution(id, codename, description, release) elif id == "Debian": diff --git a/debian/changelog b/debian/changelog index 928493ad..5f1f2967 100644 --- a/debian/changelog +++ b/debian/changelog @@ -32,8 +32,10 @@ python-apt (0.7.92) UNRELEASED; urgency=low - Merge Configuration,ConfigurationPtr,ConfigurationSub into one type. - Simplify the whole build process by using a single setup.py. - The documentation has been restructured and enhanced with tutorials. + - Only recommend lsb-release instead of depending on it. Default to + Debian unstable if lsb_release is not available. - -- Julian Andres Klode Wed, 15 Jul 2009 14:56:24 +0200 + -- Julian Andres Klode Sun, 02 Aug 2009 16:35:42 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/debian/control b/debian/control index 69bca37a..6b96a6be 100644 --- a/debian/control +++ b/debian/control @@ -24,8 +24,8 @@ Vcs-Browser: http://bzr.debian.org/loggerhead/apt/python-apt/debian-sid/changes Package: python-apt Architecture: any -Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, lsb-release -Recommends: iso-codes, libjs-jquery +Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends} +Recommends: lsb-release, iso-codes, libjs-jquery Breaks: debdelta (<< 0.28~) Provides: ${python:Provides} Suggests: python-apt-dbg, python-gtk2, python-vte -- cgit v1.2.3 From e643b71504412a6d70a10449845eecdd72529df0 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 17 Aug 2009 16:21:41 +0200 Subject: python/arfile.cc: Introduce DebFile. This is the final commit which Closes: #536096, as everything doable with the functions can now be done using the classes. --- debian/changelog | 4 +- python/apt_instmodule.cc | 1 + python/apt_instmodule.h | 1 + python/arfile.cc | 171 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 1d735656..d644d7e6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low - Make AcquireFile a subclass of AcquireItem, thus inheriting attributes. - New progress handling in apt.progress.base and apt.progress.text. Still missing Qt4 progress handlers. + - Classes in apt_inst (Closes: #536096) * Unification of dependency handling: - apt_pkg.parse_[src_]depends() now use CompType instead of CompTypeDeb @@ -34,8 +35,9 @@ python-apt (0.7.92) UNRELEASED; urgency=low - The documentation has been restructured and enhanced with tutorials. - Only recommend lsb-release instead of depending on it. Default to Debian unstable if lsb_release is not available. + * - -- Julian Andres Klode Sun, 02 Aug 2009 16:35:42 +0200 + -- Julian Andres Klode Mon, 17 Aug 2009 16:19:51 +0200 python-apt (0.7.91) experimental; urgency=low diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index 3baaf985..9cb166ed 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -207,6 +207,7 @@ extern "C" void initapt_inst() ADDTYPE(module,"ArMember",&PyArMember_Type); ADDTYPE(module,"ArArchive",&PyArArchive_Type); + ADDTYPE(module,"DebFile",&PyDebFile_Type); ADDTYPE(module,"TarFile",&PyTarFile_Type); ADDTYPE(module,"TarMember",&PyTarMember_Type); RETURN(module); diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h index 94ada0f8..9f978e44 100644 --- a/python/apt_instmodule.h +++ b/python/apt_instmodule.h @@ -22,6 +22,7 @@ extern char *doc_tarExtract; extern PyTypeObject PyArMember_Type; extern PyTypeObject PyArArchive_Type; +extern PyTypeObject PyDebFile_Type; extern PyTypeObject PyTarFile_Type; extern PyTypeObject PyTarMember_Type; diff --git a/python/arfile.cc b/python/arfile.cc index 5ac0f727..1abb738f 100644 --- a/python/arfile.cc +++ b/python/arfile.cc @@ -473,3 +473,174 @@ PyTypeObject PyArArchive_Type = { 0, // tp_alloc ararchive_new // tp_new }; + +/** + * 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.{lzma,bz2,gz} and + * data.tar.{lzma,bz2,gz} 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 + * kind of AR archive as an AR archive with some extras. + */ +struct PyDebFileObject : PyArArchiveObject { + PyObject *data; + PyObject *control; + PyObject *debian_binary; +}; + +static PyObject *debfile_get_data(PyDebFileObject *self) +{ + return Py_INCREF(self->data), self->data; +} + +static PyObject *debfile_get_control(PyDebFileObject *self) +{ + return Py_INCREF(self->control), self->control; +} + +static PyObject *debfile_get_debian_binary(PyDebFileObject *self) +{ + return Py_INCREF(self->debian_binary), self->debian_binary; +} + +static PyObject *_gettar(PyDebFileObject *self, const ARArchive::Member *m, + const char *comp) +{ + if (!m) + return 0; + PyTarFileObject *tarfile = (PyTarFileObject*)CppOwnedPyObject_NEW(self,&PyTarFile_Type); + new (&tarfile->Fd) FileFd(self->Fd); + tarfile->min = m->Start; + tarfile->Object = new ExtractTar(self->Fd, m->Size, comp); + return tarfile; +} + + + +static PyObject *debfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyDebFileObject *self = (PyDebFileObject*)ararchive_new(type, args, kwds); + + // DebFile + self->control = _gettar(self, self->Object->FindMember("control.tar.gz"), + "gzip"); + if (!self->control) + 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) + return PyErr_Format(PyExc_SystemError, "No debian archive, missing %s", + "data.tar.gz or data.tar.bz2 or data.tar.lzma"); + + + const ARArchive::Member *member = self->Object->FindMember("debian-binary"); + if (!member) + return PyErr_Format(PyExc_SystemError, "No debian archive, missing %s", + "debian-binary"); + + if (!self->Fd.Seek(member->Start)) + return HandleErrors(); + + char* value = new char[member->Size]; + self->Fd.Read(value, member->Size, true); + self->debian_binary = PyBytes_FromStringAndSize(value, member->Size); + delete[] value; + return self; +} + +static int debfile_traverse(PyObject *_self, visitproc visit, void* arg) +{ + PyDebFileObject *self = (PyDebFileObject*)_self; + Py_VISIT(self->data); + Py_VISIT(self->control); + Py_VISIT(self->debian_binary); + return PyArArchive_Type.tp_traverse(self, visit, arg); +} + +static int debfile_clear(PyObject *_self) { + PyDebFileObject *self = (PyDebFileObject*)_self; + Py_CLEAR(self->data); + Py_CLEAR(self->control); + Py_CLEAR(self->debian_binary); + return PyArArchive_Type.tp_clear(self); +} + +static void debfile_dealloc(PyObject *self) { + debfile_clear((PyDebFileObject *)self); + PyArArchive_Type.tp_dealloc(self); +} + +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} member."}, + {"debian_binary",(getter)debfile_get_debian_binary,0, + "The package version, as contained in debian-binary."}, + {NULL} +}; + +static const char *debfile_doc = + "DebFile(file: str/int/file)\n\n" + "A DebFile object represents a file in the .deb package format.\n\n" + "The parameter 'file' may be a string specifying the path of a file, or\n" + "a file-like object providing the fileno() method. It may also be an int\n" + "specifying a file descriptor (returned by e.g. os.open()).\n" + "The recommended way 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}\n" + ",debian-binary members in the archive."; + +PyTypeObject PyDebFile_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_inst.DebFile", // tp_name + sizeof(PyDebFileObject), // tp_basicsize + 0, // tp_itemsize + // Methods + debfile_dealloc, // 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_HAVE_GC, + debfile_doc, // tp_doc + debfile_traverse, // tp_traverse + debfile_clear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + debfile_getset, // tp_getset + &PyArArchive_Type, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + debfile_new // tp_new +}; -- cgit v1.2.3 From f69208a3dc27357b19aad7879efca4300d56d8bb Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 18 Aug 2009 13:40:51 +0200 Subject: debian/changelog: Classes in apt_inst now close LP: #44493. --- debian/changelog | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index d644d7e6..d92ae907 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low - New progress handling in apt.progress.base and apt.progress.text. Still missing Qt4 progress handlers. - Classes in apt_inst (Closes: #536096) + + You can now use apt_inst.DebFile.data to access the data.tar.* member + regardless of its compression (LP: #44493) * Unification of dependency handling: - apt_pkg.parse_[src_]depends() now use CompType instead of CompTypeDeb @@ -37,7 +39,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low Debian unstable if lsb_release is not available. * - -- Julian Andres Klode Mon, 17 Aug 2009 16:19:51 +0200 + -- Julian Andres Klode Tue, 18 Aug 2009 13:38:55 +0200 python-apt (0.7.91) experimental; urgency=low -- cgit v1.2.3 From ade471a3a99d33ae848874dba94576f191d3c7ca Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 18 Aug 2009 15:33:16 +0200 Subject: debian/copyright: Update. --- debian/copyright | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/copyright b/debian/copyright index 8599328a..2df6807a 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,9 +1,17 @@ -Format-Specification: http://wiki.debian.org/Proposals/CopyrightFormat?action=recall&rev=443 +Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=59 Files: * Copyright: © 2004-2009 Canonical Ltd. + © 2009 Julian Andres Klode License: GPL-2+ +Files: tests/test_all.py, tests/test_hashes.py, utils/doclint.py +Copyright: © 2009 Julian Andres Klode +License: + 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. + Files: aptsources/*.py Copyright: © 2004-2009 Canonical Ltd. Copyright: © 2005 Gustavo Noronha Silva -- cgit v1.2.3 From e3c630140e6595126046866a40e11e90c74278f2 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 18 Aug 2009 16:45:56 +0200 Subject: Set distribution to experimental --- debian/changelog | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index d92ae907..08035874 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -python-apt (0.7.92) UNRELEASED; urgency=low +python-apt (0.7.92) experimental; urgency=low * New features: - Provide a C++ API in the package python-apt-dev (Closes: #334923). @@ -37,9 +37,8 @@ python-apt (0.7.92) UNRELEASED; urgency=low - The documentation has been restructured and enhanced with tutorials. - Only recommend lsb-release instead of depending on it. Default to Debian unstable if lsb_release is not available. - * - -- Julian Andres Klode Tue, 18 Aug 2009 13:38:55 +0200 + -- Julian Andres Klode Tue, 18 Aug 2009 16:42:56 +0200 python-apt (0.7.91) experimental; urgency=low -- cgit v1.2.3 From 2ccb7545bb8c869f5f6192569a47a7522b6fbc83 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 25 Oct 2009 14:57:38 +0100 Subject: Add a tutorial on how to do things which are possible with apt-get, like apt-get --print-uris update (cf. #551164). --- debian/changelog | 4 ++- doc/source/examples/update-print-uris.py | 22 ++++++++++++++++ doc/source/tutorials/apt-get.rst | 45 ++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 doc/source/examples/update-print-uris.py create mode 100644 doc/source/tutorials/apt-get.rst (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index 7588d35a..fb3b72f9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,8 @@ -python-apt (0.7.93) experimental; urgency=low +python-apt (0.7.93) UNRELEASED; urgency=low * Merge 0.7.13.0 - 0.7.13.3 from unstable. + * Add a tutorial on how to do things which are possible with apt-get, + like apt-get --print-uris update (cf. #551164). -- Julian Andres Klode Wed, 16 Sep 2009 19:26:17 +0200 diff --git a/doc/source/examples/update-print-uris.py b/doc/source/examples/update-print-uris.py new file mode 100644 index 00000000..f078cdc5 --- /dev/null +++ b/doc/source/examples/update-print-uris.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +"""Print out the URIs of all indexes files. + +This behaves somewhat like apt-get --print-uris update.""" +import apt_pkg + +def main(): + apt_pkg.init_config() + apt_pkg.init_system() + acquire = apt_pkg.Acquire() + slist = apt_pkg.SourceList() + # Read the list + slist.read_main_list() + # Add all indexes to the fetcher. + slist.get_indexes(acquire, True) + + # Now print the URI of every item. + for item in acquire.items: + print item.desc_uri + +if __name__ == '__main__': + main() diff --git a/doc/source/tutorials/apt-get.rst b/doc/source/tutorials/apt-get.rst new file mode 100644 index 00000000..575f0c46 --- /dev/null +++ b/doc/source/tutorials/apt-get.rst @@ -0,0 +1,45 @@ +Doing stuff :command:`apt-get` does +=================================== +:Author: Julian Andres Klode +:Release: |release| +:Date: |today| + +The following article will show how you can use python-apt to do actions done +by the :command:`apt-get` command. + + +Printing the URIs of all index files +------------------------------------ +We all now that we can print the URIs of all our index files by running a +simple ``apt-get -s --print-uris update``. We can do the same. Responsible for +the source entries is the class :class:`apt_pkg.SourceList`, which can be +combined with an :class:`apt_pkg.Acquire` object using :meth:`get_indexes`. + +First of all, we have to create the objects:: + + acquire = apt_pkg.Acquire() + slist = apt_pkg.SourceList() + +Now we have to parse /etc/apt/sources.list and its friends, by using +:meth:`apt_pkg.SourceList.read_main_list`:: + slist.read_main_list() + +Now the **slist** object knows about the location of the indexes. We now have +to load those indexes into the *acquire* object by calling +:meth:`apt_pkg.SourceList.get_indexes`:: + + slist.get_indexes(acquire, True) + +The first argument is the acquire object into which we will load these indexes, +and the second argument means that we want to fetch all indexes. Now the only +thing left to do is iterating over the list of items and printing out their +URIs. Luckily, there is :attr:`apt_pkg.Acquire.items` which allows us to +iterate over the items:: + + for item in acquire.items: + print item.desc_uri + +In the end a program could look like this: + +.. literalinclude:: ../examples/update-print-uris.py + -- cgit v1.2.3