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. --- python/generic.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'python/generic.h') 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 -- cgit v1.2.3 From e72b1f224007c0f7d6059ee59b0ead6ab2ff628d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 17 Apr 2009 18:16:58 +0200 Subject: * python/generic.h: Force 0.7 compatibility to be off in Python 3 builds --- python/generic.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index 6e66d24c..ae2871e3 100644 --- a/python/generic.h +++ b/python/generic.h @@ -54,6 +54,8 @@ typedef int Py_ssize_t; #define PyString_AsString(op) PyBytes_AsString(PyUnicode_AsUTF8String(op)) #define PyInt_Check PyLong_Check #define PyInt_AsLong PyLong_AsLong +// Force 0.7 compatibility to be off in Python 3 builds +#undef COMPAT_0_7 #else #define PyBytes_Check PyString_Check #define PyBytes_AsString PyString_AsString -- cgit v1.2.3 From 1040f7f6ec9cf689d6530827348a63daad52b3ef Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 8 Jun 2009 17:17:48 +0200 Subject: python/generic.h,tag.cc,configuration.cc: Use tp_alloc/tp_free instead of PyObject_NEW/DEL This allows us to finally implement subclassing. Previously deletion of an instance of a subclass caused segmentation faults, this is not the case anymore. --- python/configuration.cc | 3 ++- python/generic.h | 12 ++++++------ python/tag.cc | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'python/generic.h') diff --git a/python/configuration.cc b/python/configuration.cc index 81dd78ac..3c6ea88c 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -161,7 +161,8 @@ static PyObject *CnfSubTree(PyObject *Self,PyObject *Args) } // Create a new sub configuration. - SubConfiguration *New = PyObject_NEW(SubConfiguration,&ConfigurationSubType); + SubConfiguration *New = (SubConfiguration*)(&ConfigurationSubType) + ->tp_alloc(&ConfigurationSubType,0); new (&New->Object) Configuration(Itm); New->Owner = Self; Py_INCREF(Self); diff --git a/python/generic.h b/python/generic.h index ae2871e3..df4d8755 100644 --- a/python/generic.h +++ b/python/generic.h @@ -99,7 +99,7 @@ inline PyObject *GetOwner(PyObject *Obj) template inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type) { - CppPyObject *New = PyObject_NEW(CppPyObject,Type); + CppPyObject *New = (CppPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T; return New; } @@ -107,7 +107,7 @@ inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type) template inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type,A const &Arg) { - CppPyObject *New = PyObject_NEW(CppPyObject,Type); + CppPyObject *New = (CppPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); return New; } @@ -116,7 +116,7 @@ template inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type) { - CppOwnedPyObject *New = PyObject_NEW(CppOwnedPyObject,Type); + CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T; New->Owner = Owner; Py_INCREF(Owner); @@ -127,7 +127,7 @@ template inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type,A const &Arg) { - CppOwnedPyObject *New = PyObject_NEW(CppOwnedPyObject,Type); + CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); New->Owner = Owner; if (Owner != 0) @@ -140,7 +140,7 @@ template void CppDealloc(PyObject *Obj) { GetCpp(Obj).~T(); - PyObject_DEL(Obj); + Obj->ob_type->tp_free(Obj); } template @@ -150,7 +150,7 @@ void CppOwnedDealloc(PyObject *iObj) Obj->Object.~T(); if (Obj->Owner != 0) Py_DECREF(Obj->Owner); - PyObject_DEL(Obj); + iObj->ob_type->tp_free(iObj); } inline PyObject *CppPyString(std::string Str) diff --git a/python/tag.cc b/python/tag.cc index 5a31488c..31491c90 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -68,7 +68,7 @@ void TagFileFree(PyObject *Obj) Self->Object.~pkgTagFile(); Self->Fd.~FileFd(); Py_DECREF(Self->File); - PyObject_DEL(Obj); + Obj->ob_type->tp_free(Obj); } /*}}}*/ @@ -246,7 +246,7 @@ static PyObject *TagSecNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { return 0; // Create the object.. - TagSecData *New = PyObject_NEW(TagSecData,type); + TagSecData *New = (TagSecData*)type->tp_alloc(type, 0); new (&New->Object) pkgTagSection(); New->Data = new char[strlen(Data)+2]; snprintf(New->Data,strlen(Data)+2,"%s\n",Data); @@ -286,14 +286,14 @@ static PyObject *TagFileNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) if (fileno == -1) return 0; - TagFileData *New = PyObject_NEW(TagFileData,type); + TagFileData *New = (TagFileData*)type->tp_alloc(type, 0); new (&New->Fd) FileFd(fileno,false); New->File = File; Py_INCREF(New->File); new (&New->Object) pkgTagFile(&New->Fd); // Create the section - New->Section = PyObject_NEW(TagSecData,&TagSecType); + New->Section = (TagSecData*)(&TagSecType)->tp_alloc(&TagSecType, 0); new (&New->Section->Object) pkgTagSection(); New->Section->Data = 0; -- 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 'python/generic.h') 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 13423bbbafc823740126e90ef0d7ca6e76fc7341 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 21 Jun 2009 19:47:31 +0200 Subject: python: Make all CppOwnedPyObjects and similar support garbage collection. If you want to subclass apt_pkg.Cache() and create an apt_pkg.DepCache() object in it (e.g. as self.depcache) this is needed because otherwise, Python would not know about the cyclic dependency and refuse to free any of them. This also changes apt_pkg.Cache to the standard deallocation schema, because the underlying CacheFile deletes its pointers automatically on deletion. Thus a second call is not needed. --- python/acquire.cc | 7 +++--- python/cache.cc | 62 ++++++++++++++++++++++++---------------------------- python/depcache.cc | 23 ++++++++++--------- python/generic.h | 44 +++++++++++++++++++++++++++++++++---- python/indexfile.cc | 6 ++--- python/pkgrecords.cc | 7 +++--- python/policy.cc | 9 ++++---- python/tag.cc | 37 +++++++++++++++++++++++-------- 8 files changed, 125 insertions(+), 70 deletions(-) (limited to 'python/generic.h') diff --git a/python/acquire.cc b/python/acquire.cc index 704ad0bd..b0dd2cab 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -372,10 +372,11 @@ PyTypeObject PkgAcquireFileType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), doc_PkgAcquireFile, // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter diff --git a/python/cache.cc b/python/cache.cc index a8da6696..4624dc34 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -241,19 +241,6 @@ static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) return CppOwnedPyObject_NEW(Self,&PackageType,Pkg); } -// we need a special dealloc here to make sure that the CacheFile -// is closed before deallocation the cache (otherwise we have a bad) -// memory leak -void PkgCacheFileDealloc(PyObject *Self) -{ - PyObject *CacheFilePy = GetOwner(Self); - pkgCacheFile *CacheF = GetCpp(CacheFilePy); - CacheF->Close(); - // Do not delete the pointer here, because it has already been deleted by - // closing the cache file. - CppOwnedDealloc(Self); -} - static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { PyObject *pyCallbackInst = 0; @@ -320,7 +307,7 @@ PyTypeObject PkgCacheType = sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize // Methods - PkgCacheFileDealloc, // tp_dealloc + CppOwnedDealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -336,10 +323,11 @@ PyTypeObject PkgCacheType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), doc_PkgCache, // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -460,7 +448,10 @@ PyTypeObject PkgListType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT , // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + 0, // tp_doc + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear }; #define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \ @@ -581,10 +572,10 @@ PyTypeObject PackageType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags "Package Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear,// tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -672,10 +663,10 @@ PyTypeObject DescriptionType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags "apt_pkg.Description Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear,// tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -935,10 +926,10 @@ PyTypeObject VersionType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags "Version Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear,// tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -1098,10 +1089,10 @@ PyTypeObject PackageFileType = { 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags "apt_pkg.PackageFile Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -1274,10 +1265,10 @@ PyTypeObject DependencyType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags "Dependency Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -1362,7 +1353,10 @@ PyTypeObject RDepListType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + "DependencyList Object", // tp_doc + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear }; /*}}}*/ diff --git a/python/depcache.cc b/python/depcache.cc index 7cf8e0a2..d0b233b8 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -677,10 +677,11 @@ PyTypeObject PkgDepCacheType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), doc_PkgDepCache, // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -866,10 +867,11 @@ PyTypeObject PkgProblemResolverType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), "ProblemResolver Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -984,10 +986,11 @@ PyTypeObject PkgActionGroupType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), doc_PkgActionGroup, // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -1002,7 +1005,7 @@ PyTypeObject PkgActionGroupType = 0, // tp_dictoffset 0, // tp_init 0, // tp_alloc - PkgActionGroupNew, // tp_new + PkgActionGroupNew, // tp_new }; #ifdef COMPAT_0_7 diff --git a/python/generic.h b/python/generic.h index b7b958f5..a9e6b8bf 100644 --- a/python/generic.h +++ b/python/generic.h @@ -29,6 +29,7 @@ #include #include +#include #include #if PYTHON_API_VERSION < 1013 @@ -99,6 +100,9 @@ inline PyObject *GetOwner(PyObject *Obj) template inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << " ===\n"; + #endif CppPyObject *New = (CppPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T; return New; @@ -107,6 +111,9 @@ inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type) template inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type,A const &Arg) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << " ===\n"; + #endif CppPyObject *New = (CppPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); return New; @@ -116,6 +123,9 @@ template inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n"; + #endif CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T; New->Owner = Owner; @@ -127,6 +137,9 @@ template inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type,A const &Arg) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n"; + #endif CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); New->Owner = Owner; @@ -135,10 +148,26 @@ inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, return New; } +// Traversal and Clean for owned objects +template +int CppOwnedTraverse(PyObject *self, visitproc visit, void* arg) { + Py_VISIT(((CppOwnedPyObject *)self)->Owner); + return 0; +} + +template +int CppOwnedClear(PyObject *self) { + Py_CLEAR(((CppOwnedPyObject *)self)->Owner); + return 0; +} + // Generic Dealloc type functions template void CppDealloc(PyObject *Obj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << " ===\n"; + #endif GetCpp(Obj).~T(); Obj->ob_type->tp_free(Obj); } @@ -146,10 +175,12 @@ void CppDealloc(PyObject *Obj) template void CppOwnedDealloc(PyObject *iObj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "+ ===\n"; + #endif CppOwnedPyObject *Obj = (CppOwnedPyObject *)iObj; Obj->Object.~T(); - if (Obj->Owner != 0) - Py_DECREF(Obj->Owner); + CppOwnedClear(iObj); iObj->ob_type->tp_free(iObj); } @@ -158,6 +189,9 @@ void CppOwnedDealloc(PyObject *iObj) template void CppDeallocPtr(PyObject *Obj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "* ===\n"; + #endif delete GetCpp(Obj); Obj->ob_type->tp_free(Obj); } @@ -165,10 +199,12 @@ void CppDeallocPtr(PyObject *Obj) template void CppOwnedDeallocPtr(PyObject *iObj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "*+ ===\n"; + #endif CppOwnedPyObject *Obj = (CppOwnedPyObject *)iObj; delete Obj->Object; - if (Obj->Owner != 0) - Py_DECREF(Obj->Owner); + CppOwnedClear(iObj); iObj->ob_type->tp_free(iObj); } diff --git a/python/indexfile.cc b/python/indexfile.cc index ba709872..ef88c2f0 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -114,10 +114,10 @@ PyTypeObject PackageIndexFileType = 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags "pkgIndexFile Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc index 1e36259d..4a3c80db 100644 --- a/python/pkgrecords.cc +++ b/python/pkgrecords.cc @@ -187,10 +187,11 @@ PyTypeObject PkgRecordsType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), "Records Object", // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter diff --git a/python/policy.cc b/python/policy.cc index 992a1192..39bbc1a3 100644 --- a/python/policy.cc +++ b/python/policy.cc @@ -167,15 +167,16 @@ PyTypeObject PyPolicy_Type = { 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), Policy_doc, // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext - Policy_Methods, // tp_methods + Policy_Methods, // tp_methods 0, // tp_members 0, // tp_getset 0, // tp_base diff --git a/python/tag.cc b/python/tag.cc index 05423e3d..74857fe5 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -34,7 +34,7 @@ using namespace std; /*}}}*/ /* We need to keep a private copy of the data.. */ -struct TagSecData : public CppPyObject +struct TagSecData : public CppOwnedPyObject { char *Data; }; @@ -47,6 +47,18 @@ struct TagFileData : public PyObject FileFd Fd; }; +// Traversal and Clean for owned objects +int TagFileTraverse(PyObject *self, visitproc visit, void* arg) { + Py_VISIT(((TagFileData *)self)->Section); + return 0; +} + +int TagFileClear(PyObject *self) { + Py_CLEAR(((TagFileData *)self)->Section); + return 0; +} + + /*}}}*/ // TagSecFree - Free a Tag Section /*{{{*/ // --------------------------------------------------------------------- @@ -55,7 +67,7 @@ void TagSecFree(PyObject *Obj) { TagSecData *Self = (TagSecData *)Obj; delete [] Self->Data; - CppDealloc(Obj); + CppOwnedDealloc(Obj); } /*}}}*/ // TagFileFree - Free a Tag File /*{{{*/ @@ -63,8 +75,11 @@ void TagSecFree(PyObject *Obj) /* */ void TagFileFree(PyObject *Obj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "^ ===\n"; + #endif TagFileData *Self = (TagFileData *)Obj; - Py_DECREF((PyObject *)Self->Section); + TagFileClear(Obj); Self->Object.~pkgTagFile(); Self->Fd.~FileFd(); Py_DECREF(Self->File); @@ -298,6 +313,8 @@ static PyObject *TagFileNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) // Create the section New->Section = (TagSecData*)(&TagSecType)->tp_alloc(&TagSecType, 0); new (&New->Section->Object) pkgTagSection(); + New->Section->Owner = New; + Py_INCREF(New->Section->Owner); New->Section->Data = 0; return HandleErrors(New); @@ -441,10 +458,11 @@ PyTypeObject TagSecType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), doc_TagSec, // tp_doc - 0, // tp_traverse - 0, // tp_clear + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter @@ -529,10 +547,11 @@ PyTypeObject TagFileType = 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), doc_TagFile, // tp_doc - 0, // tp_traverse - 0, // tp_clear + TagFileTraverse, // tp_traverse + TagFileClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter -- cgit v1.2.3 From 5e72b1f4f302e86a75399694d293e09a58d4bdbe Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 21 Jun 2009 21:05:24 +0200 Subject: python/generic.h: Define a compat macro PyErr_WarnEx for Python 2.4 --- python/generic.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index a9e6b8bf..4fe1f915 100644 --- a/python/generic.h +++ b/python/generic.h @@ -63,6 +63,11 @@ typedef int Py_ssize_t; #define PyBytes_AsStringAndSize PyString_AsStringAndSize #endif +// Hacks to make Python 2.4 build. +#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4 +#define PyErr_WarnEx(cat,msg,stacklevel) PyErr_Warn(cat,msg) +#endif + template struct CppPyObject : public PyObject { // We are only using CppPyObject and friends as dumb structs only, ie the -- cgit v1.2.3 From ca4408170dd5d2a6bba176409e0f0af1156357a6 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 25 Jun 2009 17:37:23 +0200 Subject: python/cache.cc: Support unicode objects and str objects in Python 2. --- python/cache.cc | 13 ++++++------- python/generic.cc | 3 ++- python/generic.h | 27 ++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 9 deletions(-) (limited to 'python/generic.h') diff --git a/python/cache.cc b/python/cache.cc index 4ce3178c..2de9c76a 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -219,21 +219,20 @@ static PyGetSetDef PkgCacheGetSet[] = { {} }; + + // Map access, operator [] static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) { pkgCache *Cache = GetCpp(Self); - if (PyString_Check(Arg) == 0) - { - PyObject *repr = PyObject_Repr(Arg); - PyErr_SetObject(PyExc_TypeError, repr); - Py_DECREF(repr); + // Get the name of the package, unicode and normal strings. + const char *Name = PyObject_AsString(Arg); + if (Name == NULL) return 0; - } + // Search for the package - const char *Name = PyString_AsString(Arg); pkgCache::PkgIterator Pkg = Cache->FindPkg(Name); if (Pkg.end() == true) { diff --git a/python/generic.cc b/python/generic.cc index 7309d978..51439a1b 100644 --- a/python/generic.cc +++ b/python/generic.cc @@ -25,8 +25,9 @@ PyObject *HandleErrors(PyObject *Res) return Res; } - if (Res != 0) + if (Res != 0) { Py_DECREF(Res); + } string Err; int errcnt = 0; diff --git a/python/generic.h b/python/generic.h index 4fe1f915..2a87b39c 100644 --- a/python/generic.h +++ b/python/generic.h @@ -52,22 +52,47 @@ typedef int Py_ssize_t; #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 PyString_AsString PyUnicode_AsString #define PyInt_Check PyLong_Check #define PyInt_AsLong PyLong_AsLong // Force 0.7 compatibility to be off in Python 3 builds #undef COMPAT_0_7 #else +// Compatibility for Python 2.5 and previous. +#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 5) #define PyBytes_Check PyString_Check #define PyBytes_AsString PyString_AsString #define PyBytes_AsStringAndSize PyString_AsStringAndSize #endif +#endif // Hacks to make Python 2.4 build. #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4 #define PyErr_WarnEx(cat,msg,stacklevel) PyErr_Warn(cat,msg) #endif + +static inline const char *PyUnicode_AsString(PyObject *op) { + // Convert to bytes object, using the default encoding. + PyObject *bytes = PyUnicode_AsEncodedString(op,0,0); + if (!bytes) + return 0; + const char *result = PyBytes_AsString(bytes); + Py_DECREF(bytes); + return result; +} + +// Convert any type of string based object to a const char. +static inline const char *PyObject_AsString(PyObject *object) { + if (PyBytes_Check(object)) + return PyBytes_AsString(object); + else if (PyUnicode_Check(object)) + return PyUnicode_AsString(object); + else + PyErr_SetObject(PyExc_TypeError, object); + return 0; +} + template struct CppPyObject : public PyObject { // We are only using CppPyObject and friends as dumb structs only, ie the -- cgit v1.2.3 From 128c1f00b2006c9c24638c11000e1864fc15bd04 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 25 Jun 2009 18:11:13 +0200 Subject: python/generic.h: Make PyObject_AsString() only accept unicode on Python 3. --- python/generic.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index 2a87b39c..182b1b53 100644 --- a/python/generic.h +++ b/python/generic.h @@ -83,15 +83,25 @@ static inline const char *PyUnicode_AsString(PyObject *op) { } // Convert any type of string based object to a const char. +#if PY_MAJOR_VERSION < 3 static inline const char *PyObject_AsString(PyObject *object) { if (PyBytes_Check(object)) return PyBytes_AsString(object); else if (PyUnicode_Check(object)) return PyUnicode_AsString(object); else - PyErr_SetObject(PyExc_TypeError, object); + PyErr_SetString(PyExc_TypeError, "Argument must be str."); return 0; } +#else +static inline const char *PyObject_AsString(PyObject *object) { + if (PyUnicode_Check(object) == 0) { + PyErr_SetString(PyExc_TypeError, "Argument must be str."); + return 0; + } + return PyUnicode_AsString(object); +} +#endif template struct CppPyObject : public PyObject { -- cgit v1.2.3 From e80500e7173387acc7a6b6be9d7424a4343ec036 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 25 Jun 2009 18:53:47 +0200 Subject: python: Use PyVarObject_HEAD_INIT() instead of PyObject_HEAD_INIT(). This is related to PEP 3123 and fixes some compiler warnings. --- python/acquire.cc | 17 ++++------------- python/cache.cc | 45 +++++++++------------------------------------ python/cdrom.cc | 5 +---- python/configuration.cc | 15 +++------------ python/depcache.cc | 15 +++------------ python/generic.h | 1 + python/hashstring.cc | 5 +---- python/indexfile.cc | 5 +---- python/indexrecords.cc | 5 +---- python/metaindex.cc | 5 +---- python/pkgmanager.cc | 5 +---- python/pkgrecords.cc | 5 +---- python/pkgsrcrecords.cc | 5 +---- python/policy.cc | 5 +---- python/sourcelist.cc | 5 +---- python/tag.cc | 12 ++++-------- 16 files changed, 34 insertions(+), 121 deletions(-) (limited to 'python/generic.h') diff --git a/python/acquire.cc b/python/acquire.cc index a36012bc..6c6c2ea4 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -105,10 +105,7 @@ static PyObject *AcquireItemRepr(PyObject *Self) PyTypeObject AcquireItemType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.AcquireItem", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -267,10 +264,7 @@ static char *doc_PkgAcquire = "Acquire(progress) -> Acquire() object.\n\n" PyTypeObject PkgAcquireType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Acquire", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize @@ -360,11 +354,8 @@ static char *doc_PkgAcquireFile = PyTypeObject PkgAcquireFileType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif - "apt_pkg.AcquireFile", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireFile", // tp_name sizeof(CppOwnedPyObject),// tp_basicsize 0, // tp_itemsize // Methods diff --git a/python/cache.cc b/python/cache.cc index 0f5e27eb..a571788f 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -299,10 +299,7 @@ static char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n" static PyMappingMethods CacheMap = {0,CacheMapOp,0}; PyTypeObject PkgCacheType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Cache", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -349,10 +346,7 @@ PyTypeObject PkgCacheType = // --------------------------------------------------------------------- PyTypeObject PkgCacheFileType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "pkgCacheFile", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -425,10 +419,7 @@ static PySequenceMethods PkgListSeq = PyTypeObject PkgListType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.PackageList", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -550,10 +541,7 @@ static PyObject *PackageRepr(PyObject *Self) PyTypeObject PackageType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Package", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -641,10 +629,7 @@ static PyObject *DescriptionRepr(PyObject *Self) PyTypeObject DescriptionType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Description", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -904,10 +889,7 @@ static PyGetSetDef VersionGetSet[] = { PyTypeObject VersionType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Version", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -1068,10 +1050,7 @@ static PyGetSetDef PackageFileGetSet[] = { }; PyTypeObject PackageFileType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.PackageFile", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -1243,10 +1222,7 @@ static PyGetSetDef DependencyGetSet[] = { PyTypeObject DependencyType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Dependency", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -1331,10 +1307,7 @@ static PySequenceMethods RDepListSeq = PyTypeObject RDepListType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.DependencyList", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/cdrom.cc b/python/cdrom.cc index e2651670..492afd90 100644 --- a/python/cdrom.cc +++ b/python/cdrom.cc @@ -85,10 +85,7 @@ static PyObject *PkgCdromNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) PyTypeObject PkgCdromType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Cdrom", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/configuration.cc b/python/configuration.cc index 9ef5967b..07f55957 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -503,10 +503,7 @@ 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) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Configuration", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize @@ -550,10 +547,7 @@ PyTypeObject ConfigurationType = PyTypeObject ConfigurationPtrType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.ConfigurationPtr", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize @@ -589,10 +583,7 @@ PyTypeObject ConfigurationPtrType = PyTypeObject ConfigurationSubType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.ConfigurationSub", // tp_name sizeof(SubConfiguration), // tp_basicsize 0, // tp_itemsize diff --git a/python/depcache.cc b/python/depcache.cc index 9c0c9a6f..2ce7a595 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -667,10 +667,7 @@ static char *doc_PkgDepCache = "DepCache(cache) -> DepCache() object\n\n" "The parameter *cache* refers to an apt_pkg.Cache() object."; PyTypeObject PkgDepCacheType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.DepCache", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -858,10 +855,7 @@ static PyMethodDef PkgProblemResolverMethods[] = PyTypeObject PkgProblemResolverType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.ProblemResolver", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize @@ -977,10 +971,7 @@ static char *doc_PkgActionGroup = "ActionGroup(depcache)\n\n" PyTypeObject PkgActionGroupType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.ActionGroup", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/generic.h b/python/generic.h index 182b1b53..118917cb 100644 --- a/python/generic.h +++ b/python/generic.h @@ -63,6 +63,7 @@ typedef int Py_ssize_t; #define PyBytes_Check PyString_Check #define PyBytes_AsString PyString_AsString #define PyBytes_AsStringAndSize PyString_AsStringAndSize +#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, #endif #endif diff --git a/python/hashstring.cc b/python/hashstring.cc index 23212a4b..6f70ac7e 100644 --- a/python/hashstring.cc +++ b/python/hashstring.cc @@ -95,10 +95,7 @@ static char *HashString_doc = " 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 + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.HashString", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/indexfile.cc b/python/indexfile.cc index 73f76ce6..5b526b87 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -90,10 +90,7 @@ static PyGetSetDef PackageIndexFileGetSet[] = { PyTypeObject PackageIndexFileType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.PackageIndexFile", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/indexrecords.cc b/python/indexrecords.cc index fcb2b85d..588cf883 100644 --- a/python/indexrecords.cc +++ b/python/indexrecords.cc @@ -81,10 +81,7 @@ static PyMethodDef IndexRecords_Methods[] = { 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 + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.IndexRecords", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/metaindex.cc b/python/metaindex.cc index b5d194b4..87b1e59a 100644 --- a/python/metaindex.cc +++ b/python/metaindex.cc @@ -72,10 +72,7 @@ static PyObject *MetaIndexRepr(PyObject *Self) PyTypeObject MetaIndexType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.MetaIndex", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index 668f7cfc..9e9cc32d 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -133,10 +133,7 @@ static PyGetSetDef PkgManagerGetSet[] = { PyTypeObject PkgManagerType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.PackageManager", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc index 4a3c80db..886bdb58 100644 --- a/python/pkgrecords.cc +++ b/python/pkgrecords.cc @@ -163,10 +163,7 @@ static PyObject *PkgRecordsNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) PyTypeObject PkgRecordsType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.PackageRecords", // tp_name sizeof(CppOwnedPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc index 9707dce2..187050b7 100644 --- a/python/pkgsrcrecords.cc +++ b/python/pkgsrcrecords.cc @@ -204,10 +204,7 @@ static PyObject *PkgSrcRecordsNew(PyTypeObject *type,PyObject *args,PyObject *kw PyTypeObject PkgSrcRecordsType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.SourceRecords", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/policy.cc b/python/policy.cc index 5150af91..91ed5454 100644 --- a/python/policy.cc +++ b/python/policy.cc @@ -143,10 +143,7 @@ static char *Policy_doc = "Policy(cache)\n\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 + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Policy", // tp_name sizeof(CppOwnedPyObject),// tp_basicsize 0, // tp_itemsize diff --git a/python/sourcelist.cc b/python/sourcelist.cc index 2cf5eea9..0820d5bf 100644 --- a/python/sourcelist.cc +++ b/python/sourcelist.cc @@ -115,10 +115,7 @@ static PyObject *PkgSourceListNew(PyTypeObject *type,PyObject *args,PyObject *kw PyTypeObject PkgSourceListType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.SourceList", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize diff --git a/python/tag.cc b/python/tag.cc index 1ad0a465..2b71517d 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -175,6 +175,7 @@ static PyObject *TagSecKeys(PyObject *Self,PyObject *Args) return List; } +#if PY_MAJOR_VERSION < 3 static char *doc_Exists = "Exists(Name) -> integer"; static PyObject *TagSecExists(PyObject *Self,PyObject *Args) { @@ -188,6 +189,7 @@ static PyObject *TagSecExists(PyObject *Self,PyObject *Args) return Py_BuildValue("i",0); return Py_BuildValue("i",1); } +#endif static int TagSecContains(PyObject *Self,PyObject *Arg) { @@ -436,10 +438,7 @@ static char *doc_TagSec = "TagSection(text) -> Create a new object.\n\n" "to the functions provided by the C++ class (e.g. Find)"; PyTypeObject TagSecType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.TagSection", // tp_name sizeof(TagSecData), // tp_basicsize 0, // tp_itemsize @@ -525,10 +524,7 @@ static char *doc_TagFile = "TagFile(file) -> TagFile() object. \n\n" // Type for a Tag File PyTypeObject TagFileType = { - PyObject_HEAD_INIT(&PyType_Type) - #if PY_MAJOR_VERSION < 3 - 0, // ob_size - #endif + PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.TagFile", // tp_name sizeof(TagFileData), // tp_basicsize 0, // tp_itemsize -- cgit v1.2.3 From 2d8f74890d6203c669db960c7108cad7f45c3a70 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 10 Jul 2009 19:13:16 +0200 Subject: python/generic.h: Introduce NoDelete field in CppPyObject. Setting NoDelete to true causes the deallocation functions to not delete the underlying C++ object. This is useful in situations where the object is already managed somewhere else, e.g. DepCache by CacheFile. It will also assist us in providing a flexible C++ API which only takes ownership if requested. --- python/generic.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index 118917cb..408529a5 100644 --- a/python/generic.h +++ b/python/generic.h @@ -117,6 +117,11 @@ template struct CppPyObject : public PyObject // So basically having the c'tor here removes the need for T to have a // default c'tor, which is not always desireable. CppPyObject() { }; + + // Flag which causes the underlying object to not be deleted. + bool NoDelete; + + // The underlying C++ object. T Object; }; @@ -209,7 +214,8 @@ void CppDealloc(PyObject *Obj) #ifdef ALLOC_DEBUG std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << " ===\n"; #endif - GetCpp(Obj).~T(); + if (!((CppPyObject*)Obj)->NoDelete) + GetCpp(Obj).~T(); Obj->ob_type->tp_free(Obj); } @@ -220,7 +226,8 @@ void CppOwnedDealloc(PyObject *iObj) std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "+ ===\n"; #endif CppOwnedPyObject *Obj = (CppOwnedPyObject *)iObj; - Obj->Object.~T(); + if (!((CppPyObject*)Obj)->NoDelete) + Obj->Object.~T(); CppOwnedClear(iObj); iObj->ob_type->tp_free(iObj); } @@ -233,7 +240,8 @@ void CppDeallocPtr(PyObject *Obj) #ifdef ALLOC_DEBUG std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "* ===\n"; #endif - delete GetCpp(Obj); + if (!((CppPyObject*)Obj)->NoDelete) + delete GetCpp(Obj); Obj->ob_type->tp_free(Obj); } @@ -244,7 +252,8 @@ void CppOwnedDeallocPtr(PyObject *iObj) std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "*+ ===\n"; #endif CppOwnedPyObject *Obj = (CppOwnedPyObject *)iObj; - delete Obj->Object; + if (!((CppPyObject*)Obj)->NoDelete) + delete Obj->Object; CppOwnedClear(iObj); iObj->ob_type->tp_free(iObj); } -- cgit v1.2.3 From a0ebd7b076fc359dd1f2f892aa8e70ee4ef4de2a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 13 Jul 2009 15:40:07 +0200 Subject: python/generic.h: Use PyBytes_AS_STRING instead of PyBytes_AsString in PyUnicode_AsString. --- python/generic.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index 408529a5..639578c5 100644 --- a/python/generic.h +++ b/python/generic.h @@ -61,6 +61,7 @@ typedef int Py_ssize_t; // Compatibility for Python 2.5 and previous. #if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 5) #define PyBytes_Check PyString_Check +#define PyBytes_AS_STRING PyString_AS_STRING #define PyBytes_AsString PyString_AsString #define PyBytes_AsStringAndSize PyString_AsStringAndSize #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, @@ -78,7 +79,7 @@ static inline const char *PyUnicode_AsString(PyObject *op) { PyObject *bytes = PyUnicode_AsEncodedString(op,0,0); if (!bytes) return 0; - const char *result = PyBytes_AsString(bytes); + const char *result = PyBytes_AS_STRING(bytes); Py_DECREF(bytes); return result; } -- cgit v1.2.3 From e3745827634d8334f796a1506e575ab6f5efdaee Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 14 Jul 2009 20:37:29 +0200 Subject: python/generic.h: Use Py_XINCREF instead of Py_INCREF in CppOwnedPyObject_NEW. Reason: Owner may be NULL. --- python/generic.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index 639578c5..7f3a3809 100644 --- a/python/generic.h +++ b/python/generic.h @@ -176,7 +176,7 @@ inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T; New->Owner = Owner; - Py_INCREF(Owner); + Py_XINCREF(Owner); return New; } @@ -190,8 +190,7 @@ inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); New->Owner = Owner; - if (Owner != 0) - Py_INCREF(Owner); + Py_XINCREF(Owner); return New; } -- cgit v1.2.3 From b34e27d4ebaf325df6d82fde17b28cf9a008dbfc Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 17 Jul 2009 16:07:03 +0200 Subject: python: Use PyString_FromFormat instead of snprintf. --- python/acquire.cc | 5 ++-- python/cache.cc | 67 +++++++++++++++++++++++----------------------------- python/generic.h | 1 + python/hashstring.cc | 5 ++-- python/indexfile.cc | 5 +--- python/metaindex.cc | 11 ++++----- 6 files changed, 40 insertions(+), 54 deletions(-) (limited to 'python/generic.h') diff --git a/python/acquire.cc b/python/acquire.cc index 05429d1b..50bdc949 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -287,8 +287,8 @@ static PyObject *AcquireItemRepr(PyObject *Self) pkgAcquire::Item *Itm = acquireitem_tocpp(Self); if (Itm == 0) return 0; - char S[300]; - snprintf(S,sizeof(S),"<%s object: " + + return PyString_FromFormat("<%s object: " "Status: %i Complete: %i Local: %i IsTrusted: %i " "FileSize: %lu DestFile:'%s' " "DescURI: '%s' ID:%lu ErrorText: '%s'>", @@ -296,7 +296,6 @@ static PyObject *AcquireItemRepr(PyObject *Self) 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); } static void AcquireItemDealloc(PyObject *self) { diff --git a/python/cache.cc b/python/cache.cc index c160cf69..c1f9eb2b 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -228,7 +228,7 @@ static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) const char *Name = PyObject_AsString(Arg); if (Name == NULL) return 0; - + // Search for the package pkgCache::PkgIterator Pkg = Cache->FindPkg(Name); @@ -534,11 +534,9 @@ static PyObject *PackageRepr(PyObject *Self) { pkgCache::PkgIterator &Pkg = GetCpp(Self); - char S[300]; - snprintf(S,sizeof(S),"", - Pkg.Name(),Pkg.Section(),Pkg->ID,Pkg->Flags); - return PyString_FromString(S); + return PyString_FromFormat("<%s object: name:'%s' section: " + "'%s' id:%u>", Self->ob_type->tp_name, + Pkg.Name(), Pkg.Section(), Pkg->ID); } PyTypeObject PyPackage_Type = @@ -621,12 +619,9 @@ static PyGetSetDef DescriptionGetSet[] = { static PyObject *DescriptionRepr(PyObject *Self) { pkgCache::DescIterator &Desc = GetCpp(Self); - - char S[300]; - snprintf(S,sizeof(S), - "ob_type->tp_name, Desc.LanguageCode(), + Desc.md5()); } PyTypeObject PyDescription_Type = @@ -840,15 +835,14 @@ static PyObject *VersionGetIsTrusted(PyObject *Self, void*) { static PyObject *VersionRepr(PyObject *Self) { pkgCache::VerIterator &Ver = GetCpp(Self); - - char S[300]; - snprintf(S,sizeof(S),"", - Ver.ParentPkg().Name(),Ver.VerStr(),Ver.Section(),Ver.Arch(), - (unsigned long)Ver->Size,(unsigned long)Ver->InstalledSize, - Ver->Hash,Ver->ID,Ver->Priority); - return PyString_FromString(S); + return PyString_FromFormat("<%s object: Pkg:'%s' Ver:'%s' Section:'%s' " + " Arch:'%s' Size:%lu ISize:%lu Hash:%u ID:%u " + "Priority:%u>", Self->ob_type->tp_name, + Ver.ParentPkg().Name(), Ver.VerStr(), + Ver.Section(), Ver.Arch(), + (unsigned long)Ver->Size, + (unsigned long)Ver->InstalledSize, + Ver->Hash, Ver->ID, Ver->Priority); } static PyGetSetDef VersionGetSet[] = { @@ -1004,20 +998,22 @@ static PyObject *PackageFile_GetID(PyObject *Self,void*) return Py_BuildValue("i",File->ID); } +#define S(s) (s == NULL ? "" : s) static PyObject *PackageFileRepr(PyObject *Self) { pkgCache::PkgFileIterator &File = GetCpp(Self); - char S[300]; - snprintf(S,sizeof(S),"", - File.FileName(),File.Archive(),File.Component(),File.Version(), - File.Origin(),File.Label(),File.Architecture(),File.Site(), - File.IndexType(),File->Size,File->Flags,File->ID); - return PyString_FromString(S); + return PyString_FromFormat("<%s object: filename:'%s'" + " a=%s,c=%s,v=%s,o=%s,l=%s arch='%s' site='%s'" + " IndexType='%s' Size=%lu ID:%u>", + Self->ob_type->tp_name, File.FileName(), + S(File.Archive()), + S(File.Component()),S(File.Version()), + S(File.Origin()),S(File.Label()), + S(File.Architecture()),S(File.Site()), + S(File.IndexType()),File->Size,File->ID); } +#undef S static PyGetSetDef PackageFileGetSet[] = { {(char*)"architecture",PackageFile_GetArchitecture}, @@ -1089,13 +1085,10 @@ static PyObject *DependencyRepr(PyObject *Self) { pkgCache::DepIterator &Dep = GetCpp(Self); - char S[300]; - snprintf(S,sizeof(S),"", - Dep.TargetPkg().Name(), - (Dep.TargetVer() == 0?"":Dep.TargetVer()), - Dep.CompType()); - return PyString_FromString(S); + return PyString_FromFormat("<%s object: pkg:'%s' ver:'%s' comp:'%s'>", + Self->ob_type->tp_name, Dep.TargetPkg().Name(), + (Dep.TargetVer() == 0?"":Dep.TargetVer()), + Dep.CompType()); } static PyObject *DepSmartTargetPkg(PyObject *Self,PyObject *Args) diff --git a/python/generic.h b/python/generic.h index 7f3a3809..4a55e9bf 100644 --- a/python/generic.h +++ b/python/generic.h @@ -53,6 +53,7 @@ typedef int Py_ssize_t; #define PyString_FromString PyUnicode_FromString #define PyString_FromStringAndSize PyUnicode_FromStringAndSize #define PyString_AsString PyUnicode_AsString +#define PyString_FromFormat PyUnicode_FromFormat #define PyInt_Check PyLong_Check #define PyInt_AsLong PyLong_AsLong // Force 0.7 compatibility to be off in Python 3 builds diff --git a/python/hashstring.cc b/python/hashstring.cc index b76dc127..a8d97cd8 100644 --- a/python/hashstring.cc +++ b/python/hashstring.cc @@ -42,9 +42,8 @@ static PyObject *HashString_NEW(PyTypeObject *type,PyObject *Args, 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); + return PyString_FromFormat("<%s object: \"%s\">", self->ob_type->tp_name, + hash->toStr().c_str()); } static PyObject *HashString_ToStr(PyObject *self) diff --git a/python/indexfile.cc b/python/indexfile.cc index 7bf646d0..74345ec9 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -58,16 +58,13 @@ static PyObject *PackageIndexFileGetIsTrusted(PyObject *Self,void*) { static PyObject *PackageIndexFileRepr(PyObject *Self) { pkgIndexFile *File = GetCpp(Self); - - char S[1024]; - snprintf(S,sizeof(S),"", File->GetType()->Label, File->Describe().c_str(), File->Exists(), File->HasPackages(), File->Size(), File->IsTrusted(), File->ArchiveURI("").c_str()); - return PyString_FromString(S); } static PyGetSetDef PackageIndexFileGetSet[] = { diff --git a/python/metaindex.cc b/python/metaindex.cc index d67c0ada..62ff6b90 100644 --- a/python/metaindex.cc +++ b/python/metaindex.cc @@ -64,13 +64,10 @@ static PyGetSetDef MetaIndexGetSet[] = { static PyObject *MetaIndexRepr(PyObject *Self) { metaIndex *meta = GetCpp(Self); - - char S[1024]; - snprintf(S,sizeof(S),"", - meta->GetType(), meta->GetURI().c_str(), meta->GetDist().c_str(), - meta->IsTrusted()); - return PyString_FromString(S); + return PyString_FromFormat("<%s object: type='%s', uri:'%s' dist='%s' " + "is_trusted='%i'>", Self->ob_type->tp_name, + meta->GetType(), meta->GetURI().c_str(), + meta->GetDist().c_str(), meta->IsTrusted()); } PyTypeObject PyMetaIndex_Type = -- cgit v1.2.3 From 9d97c4ef07fe249ed2b5af7d52fe15655bbb9170 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 21 Jul 2009 17:51:43 +0200 Subject: python/lock.cc: Implement apt_pkg.FileLock(). This is yet another context manager, this time for locking files. It can be used multiple times and features an internal counter. --- doc/source/whatsnew/0.8.0.rst | 6 ++ python/apt_pkgmodule.cc | 1 + python/apt_pkgmodule.h | 1 + python/generic.h | 1 + python/lock.cc | 132 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 141 insertions(+) (limited to 'python/generic.h') diff --git a/doc/source/whatsnew/0.8.0.rst b/doc/source/whatsnew/0.8.0.rst index 8889cbd9..244da388 100644 --- a/doc/source/whatsnew/0.8.0.rst +++ b/doc/source/whatsnew/0.8.0.rst @@ -79,6 +79,12 @@ Yet another context manager is available for locking the package system:: with apt_pkg.SystemLock(): # do your stuff here +There is also one for file based locking: + + with apt_pkg.FileLock(filename): + # do your stuff here + + Unification of dependency handling ---------------------------------- In apt 0.7, there were three different return types of functions parsing diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index d4c23d2f..8b8e9c7f 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -652,6 +652,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"AcquireItemDesc",&PyAcquireItemDesc_Type); ADDTYPE(Module,"CdromProgress",&PyCdromProgress_Type); ADDTYPE(Module,"SystemLock",&PySystemLock_Type); + ADDTYPE(Module,"FileLock",&PyFileLock_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 de70c056..04bce2cc 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -118,6 +118,7 @@ extern PyTypeObject PyCdromProgress_Type; extern PyTypeObject PyAcquireItemDesc_Type; extern PyTypeObject PyAcquireWorker_Type; extern PyTypeObject PySystemLock_Type; +extern PyTypeObject PyFileLock_Type; #include "python-apt.h" #endif diff --git a/python/generic.h b/python/generic.h index 4a55e9bf..d7f121ce 100644 --- a/python/generic.h +++ b/python/generic.h @@ -54,6 +54,7 @@ typedef int Py_ssize_t; #define PyString_FromStringAndSize PyUnicode_FromStringAndSize #define PyString_AsString PyUnicode_AsString #define PyString_FromFormat PyUnicode_FromFormat +#define PyString_Type PyUnicode_Type #define PyInt_Check PyLong_Check #define PyInt_AsLong PyLong_AsLong // Force 0.7 compatibility to be off in Python 3 builds diff --git a/python/lock.cc b/python/lock.cc index 75665779..d4d45734 100644 --- a/python/lock.cc +++ b/python/lock.cc @@ -131,3 +131,135 @@ PyTypeObject PySystemLock_Type = { 0, // tp_alloc systemlock_new, // tp_new }; + + +/** + * File Based locking. + * + * The counter is increased by every call to filelock_enter() and decreased by + * every call to filelock_exit(). When the counter reaches 0, the underlying + * file descriptor is closed. + * + * Members: + * @member char* filename The name of the file + * @member int lock_count How many times we have locked it. + * @member int fd The filedescriptor returned by GetLock() or 0. + */ +struct filelock_object { + PyObject_HEAD + char *filename; + int lock_count; + int fd; +}; + +static PyObject *filelock_enter(filelock_object *self, PyObject *args) +{ + self->lock_count++; + // If we have no lock yet, get a lock. + if (self->lock_count == 1) { + self->fd = GetLock(self->filename, true); + if (self->fd == -1) { + self->lock_count--; + return HandleErrors(); + } + } + Py_INCREF(self); + return (PyObject *)self; +} + +static PyObject *filelock_exit(filelock_object *self, PyObject *args) +{ + // Count down the lock_count, if it is less than 0, reset it to 0. + self->lock_count--; + if (self->lock_count < 0) + self->lock_count = 0; + if (self->lock_count == 0 && self->fd != 0 && close(self->fd) == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + Py_RETURN_FALSE; +} + +static PyObject *filelock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + char *filename = 0; + char *kwlist[] = {"filename", NULL}; + if (PyArg_ParseTupleAndKeywords(args, kwds, "s:__init__", kwlist, + &filename) == 0) { + return NULL; + } + filelock_object *self = (filelock_object *)type->tp_alloc(type, 0); + // Copy the string into the object. + self->filename = new char[strlen(filename) + 1]; + strcpy(self->filename, filename); + return (PyObject *)self; +} + +static void filelock_dealloc(filelock_object *self) +{ + delete[] self->filename; + ((PyObject*)self)->ob_type->tp_free(self); +} + +static PyMethodDef filelock_methods[] = { + {"__enter__",(PyCFunction)filelock_enter,METH_VARARGS,"Lock the system."}, + {"__exit__",(PyCFunction)filelock_exit,METH_VARARGS,"Unlock the system."}, + {NULL} +}; + +static char *filelock_doc = "SystemLock(filename: str)\n\n" + "Context manager for locking using a file. The lock is established\n" + "as soon as the method __enter__() is called. It is released when\n" + "__exit__() is called.\n\n" + "This should be used via the 'with' statement, e.g.::\n\n" + " with apt_pkg.FileLock(filename):\n" + " ...\n\n" + "Once the block is left, the lock is released automatically. The object\n" + "can be used multiple times::\n\n" + " lock = apt_pkg.FileLock(filename)\n" + " with lock:\n" + " ...\n" + " with lock:\n" + " ...\n\n"; + +PyTypeObject PyFileLock_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.FileLock", // tp_name + sizeof(filelock_object), // tp_basicsize + 0, // tp_itemsize + // Methods + destructor(filelock_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), + filelock_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + filelock_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 + filelock_new, // tp_new +}; -- cgit v1.2.3 From 7a30c8bb4b70f42cc268b4b3a75dab5b414146c4 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 24 Jul 2009 17:53:53 +0200 Subject: python/generic.h: Do not deallocate the temporary bytes object in PyUnicode_AsString. --- python/generic.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index d7f121ce..75520914 100644 --- a/python/generic.h +++ b/python/generic.h @@ -79,11 +79,7 @@ typedef int Py_ssize_t; static inline const char *PyUnicode_AsString(PyObject *op) { // Convert to bytes object, using the default encoding. PyObject *bytes = PyUnicode_AsEncodedString(op,0,0); - if (!bytes) - return 0; - const char *result = PyBytes_AS_STRING(bytes); - Py_DECREF(bytes); - return result; + return bytes ? PyBytes_AS_STRING(bytes) : 0; } // Convert any type of string based object to a const char. -- cgit v1.2.3 From e526904d0440e720cbeebf895faf884717f3fbb3 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 7 Aug 2009 17:47:25 +0200 Subject: python/arfile.cc: Introduce apt_inst.ArArchive and apt_inst.ArMember. This is part one of wishlist Bug#536096, introducing classes in apt_inst. --- python/apt_instmodule.cc | 31 ++++- python/apt_instmodule.h | 4 + python/arfile.cc | 323 +++++++++++++++++++++++++++++++++++++++++++++++ python/generic.h | 1 + setup.py | 3 +- 5 files changed, 354 insertions(+), 8 deletions(-) create mode 100644 python/arfile.cc (limited to 'python/generic.h') diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index 5aca4e00..aedccb47 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -169,11 +169,22 @@ static PyMethodDef methods[] = {} }; + +static const char *apt_inst_doc = + "Functions for working with AR,tar archives and .deb packages.\n\n" + "This module provides useful classes and functions to work with\n" + "archives, modelled after the 'TarFile' class in the 'tarfile' module."; +#define ADDTYPE(mod,name,type) { \ + if (PyType_Ready(type) == -1) RETURN(0); \ + Py_INCREF(type); \ + PyModule_AddObject(mod,name,(PyObject *)type); } + + #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "apt_inst", - "Functions for working with packages and ar,tar archives (apt-inst)", + apt_inst_doc, -1, methods, 0, @@ -181,14 +192,20 @@ static struct PyModuleDef moduledef = { 0, 0 }; - +#define RETURN(x) return x extern "C" PyObject * PyInit_apt_inst() -{ - return PyModule_Create(&moduledef); -} #else extern "C" void initapt_inst() +#define RETURN(x) +#endif { - Py_InitModule("apt_inst",methods); +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create(&moduledef); +#else + PyObject *module = Py_InitModule3("apt_inst",methods, apt_inst_doc); +#endif + + ADDTYPE(module,"ArMember",&PyArMember_Type); + ADDTYPE(module,"ArArchive",&PyArArchive_Type); + RETURN(module); } -#endif /*}}}*/ diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h index 45ba5f85..e06e344d 100644 --- a/python/apt_instmodule.h +++ b/python/apt_instmodule.h @@ -17,4 +17,8 @@ extern char *doc_debExtract; PyObject *tarExtract(PyObject *Self,PyObject *Args); extern char *doc_tarExtract; + +extern PyTypeObject PyArMember_Type; +extern PyTypeObject PyArArchive_Type; + #endif diff --git a/python/arfile.cc b/python/arfile.cc new file mode 100644 index 00000000..368fb17c --- /dev/null +++ b/python/arfile.cc @@ -0,0 +1,323 @@ +/* + * arfile.cc - Wrapper around ARArchive and ARArchive::Member. + * + * 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 +#include + +PyObject *armember_get_name(PyObject *self, void *closure) +{ + return CppPyString(GetCpp(self)->Name); +} + +PyObject *armember_get_mtime(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->MTime); +} + +PyObject *armember_get_uid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->UID); +} + +PyObject *armember_get_gid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->GID); +} + +PyObject *armember_get_mode(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Mode); +} + +PyObject *armember_get_size(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Size); +} + +PyObject *armember_get_start(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Start); +} + +PyGetSetDef armember_getset[] = { + {"gid",armember_get_gid,0,"The group id of the owner."}, + {"mode",armember_get_mode,0,"The mode of the file."}, + {"mtime",armember_get_mtime,0,"Last time of modification."}, + {"name",armember_get_name,0,"The name of the file."}, + {"size",armember_get_size,0,"The size of the files."}, + {"start",armember_get_start,0, + "The offset in the archive where the file starts."}, + {"uid",armember_get_uid,0,"The user id of the owner."}, + {NULL} +}; + +static const char *armember_doc = + "An ArMember object represents a single file within an AR archive. For\n" + "Debian packages this can be e.g. control.tar.gz. This class provides\n" + "information about this file, such as the mode and size."; +PyTypeObject PyArMember_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_inst.ArMember", // tp_name + sizeof(CppOwnedPyObject), // tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDeallocPtr, // 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, + armember_doc, // tp_doc + CppOwnedTraverse,// tp_traverse + CppOwnedClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + armember_getset, // tp_getset +}; + +struct PyArArchiveObject : public CppOwnedPyObject { + FileFd Fd; +}; + +static const char *ararchive_getmember_doc = + "getmember(name: str) -> ArMember\n\n" + "Return a ArMember object for the member given by name. Raise\n" + "LookupError if there is no ArMember with the given name."; +PyObject *ararchive_getmember(PyArArchiveObject *self, PyObject *arg) +{ + const char *name; + CppOwnedPyObject *ret; + if (! (name = PyObject_AsString(arg))) + return 0; + + const ARArchive::Member *member = self->Object->FindMember(name); + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + + // Create our object. + ret = CppOwnedPyObject_NEW(self,&PyArMember_Type); + ret->Object = const_cast(member); + ret->NoDelete = true; + return ret; +} + +static const char *ararchive_getdata_doc = + "getdata(name: str) -> bytes\n\n" + "Return the contents of the member, as a bytes object. Raise\n" + "LookupError if there is no ArMember with the given name."; +PyObject *ararchive_getdata(PyArArchiveObject *self, PyObject *args) +{ + char *name = 0; + if (PyArg_ParseTuple(args, "s:getdata", &name) == 0) + return 0; + const ARArchive::Member *member = self->Object->FindMember(name); + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + if (!self->Fd.Seek(member->Start)) + return HandleErrors(); + + char* value = new char[member->Size]; + self->Fd.Read(value, member->Size, true); + PyObject *result = PyBytes_FromStringAndSize(value, member->Size); + delete[] value; + return result; +} + +static const char *ararchive_extract_doc = + "extract(name: str[, target: str]) -> bool\n\n" + "Extract the member given by name into the directory given by target.\n" + "If the extraction failed, an error is raised. Otherwise, the method\n" + "returns True if the owner could be set or False if the owner could not\n" + "be changed. It may also raise LookupError if there is member with\n" + "the given name."; +PyObject *ararchive_extract(PyArArchiveObject *self, PyObject *args) +{ + char *name = 0; + char *target = ""; + if (PyArg_ParseTuple(args, "s|s:extract", &name, &target) == 0) + return 0; + + const ARArchive::Member *member = self->Object->FindMember(name); + + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + + if (!self->Fd.Seek(member->Start)) + return HandleErrors(); + + // Open the target file + FileFd outfd(flCombine(target,name), FileFd::WriteAny, member->Mode); + if (_error->PendingError() == true) + return HandleErrors(); + + // Temporary buffer. We should probably split this into smaller parts. + char* value = new char[member->Size]; + + // Read into the buffer + if (!self->Fd.Read(value, member->Size, true)) { + delete[] value; + return HandleErrors(); + } + if (!outfd.Write(value, member->Size)) { + delete[] value; + return HandleErrors(); + } + if (fchown(outfd.Fd(), member->UID, member->GID) == -1) { + delete[] value; + Py_RETURN_FALSE; + } + Py_RETURN_TRUE; +} + +PyMethodDef ararchive_methods[] = { + {"getmember",(PyCFunction)ararchive_getmember,METH_O, + ararchive_getmember_doc}, + {"getdata",(PyCFunction)ararchive_getdata,METH_VARARGS, + ararchive_getdata_doc}, + {"extract",(PyCFunction)ararchive_extract,METH_VARARGS, + ararchive_extract_doc}, + {NULL} +}; + +PyObject *ararchive_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *file; + PyArArchiveObject *self; + char *filename = 0; + int fileno; + if (PyArg_ParseTuple(args,"O:__new__",&file) == 0) + return 0; + + // We receive a filename. + if ((filename = (char*)PyObject_AsString(file))) { + self = (PyArArchiveObject *)CppOwnedPyObject_NEW(0,type); + new (&self->Fd) FileFd(filename,FileFd::ReadOnly); + } + // We receive a file object. + else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) { + // Clear the error set by PyObject_AsString(). + PyErr_Clear(); + self = (PyArArchiveObject *)CppOwnedPyObject_NEW(file,type); + new (&self->Fd) FileFd(fileno,false); + } + else { + return 0; + } + self->Object = new ARArchive(self->Fd); + if (_error->PendingError() == true) + return HandleErrors(); + return self; +} + +static void ararchive_dealloc(PyObject *self) { + ((PyArArchiveObject *)(self))->Fd.~FileFd(); + CppOwnedDeallocPtr(self); +} + +// Return bool or -1 (exception). +static int ararchive_contains(PyObject *self, PyObject *arg) +{ + const char *name = PyObject_AsString(arg); + if (!name) + return -1; + return (GetCpp(self)->FindMember(name) != 0); +} + +static PySequenceMethods ararchive_as_sequence = + {0,0,0,0,0,0,0,ararchive_contains,0,0}; + +static PyMappingMethods ararchive_as_mapping = + {0,(PyCFunction)ararchive_getmember,0}; + +static const char *ararchive_doc = + "ArArchive(file: str/int/file)\n\n" + "An ArArchive object represents an archive in the 4.4 BSD AR format, \n" + "which is used for e.g. deb packages.\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."; + +PyTypeObject PyArArchive_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_inst.ArArchive", // tp_name + sizeof(PyArArchiveObject), // tp_basicsize + 0, // tp_itemsize + // Methods + ararchive_dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &ararchive_as_sequence, // tp_as_sequence + &ararchive_as_mapping, // 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, + ararchive_doc, // tp_doc + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + ararchive_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 + ararchive_new // tp_new +}; diff --git a/python/generic.h b/python/generic.h index 75520914..d5d6e9fb 100644 --- a/python/generic.h +++ b/python/generic.h @@ -66,6 +66,7 @@ typedef int Py_ssize_t; #define PyBytes_AS_STRING PyString_AS_STRING #define PyBytes_AsString PyString_AsString #define PyBytes_AsStringAndSize PyString_AsStringAndSize +#define PyBytes_FromStringAndSize PyString_FromStringAndSize #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, #endif #endif diff --git a/setup.py b/setup.py index 9b33ed5d..4eb6987e 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,8 @@ files = sorted(['python/' + fname for fname in files], key=lambda s: s[:-3]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module -files = ["python/apt_instmodule.cc", "python/generic.cc", "python/tar.cc"] +files = ["python/apt_instmodule.cc", "python/generic.cc", "python/tar.cc", + "python/arfile.cc"] apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) # Replace the leading _ that is used in the templates for translation -- cgit v1.2.3