diff options
Diffstat (limited to 'python/cache.cc')
-rw-r--r-- | python/cache.cc | 1600 |
1 files changed, 1600 insertions, 0 deletions
diff --git a/python/cache.cc b/python/cache.cc new file mode 100644 index 0000000..81bbb96 --- /dev/null +++ b/python/cache.cc @@ -0,0 +1,1600 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: cache.cc,v 1.5 2003/06/03 03:03:23 mdz Exp $ +/* ###################################################################### + + Cache - Wrapper for the cache related functions + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include "generic.h" +#include "apt_pkgmodule.h" + +#include <apt-pkg/pkgcache.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/error.h> +#include <apt-pkg/packagemanager.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/update.h> + +#include <Python.h> +#include "progress.h" + +class pkgSourceList; + +// must be in sync with pkgCache::DepType in libapt +// it sucks to have it here duplicated, but we get it +// translated from libapt and that is certainly not what +// we want in a programing interface +const char *UntranslatedDepTypes[] = +{ + "", "Depends","PreDepends","Suggests", + "Recommends","Conflicts","Replaces", + "Obsoletes", "Breaks", "Enhances" +}; + + /*}}}*/ + +template<typename T> struct IterListStruct +{ + T Iter; + unsigned long LastIndex; + + IterListStruct(T const &I) : Iter(I), LastIndex(0) {} + IterListStruct() : LastIndex(0) {}; + + bool move(unsigned long Index) { + if ((unsigned)Index >= Count()) + { + PyErr_SetNone(PyExc_IndexError); + return false; + } + + if ((unsigned)Index < LastIndex) + { + LastIndex = 0; + Iter = Begin(); + } + + while ((unsigned)Index > LastIndex) + { + LastIndex++; + Iter++; + if (Iter.end() == true) + { + PyErr_SetNone(PyExc_IndexError); + return false; + } + } + return true; + } + + virtual unsigned Count() = 0; + virtual T Begin() = 0; + +}; + +struct PkgListStruct : public IterListStruct<pkgCache::PkgIterator> { + unsigned Count() { return Iter.Cache()->HeaderP->PackageCount; } + pkgCache::PkgIterator Begin() { return Iter.Cache()->PkgBegin(); } + + PkgListStruct(pkgCache::PkgIterator const &I) { Iter = I; } +}; + +struct GrpListStruct : public IterListStruct<pkgCache::GrpIterator> { + unsigned Count() { return Iter.Cache()->HeaderP->GroupCount; } + pkgCache::GrpIterator Begin() { return Iter.Cache()->GrpBegin(); } + GrpListStruct(pkgCache::GrpIterator const &I) { Iter = I; } +}; + +struct RDepListStruct +{ + pkgCache::DepIterator Iter; + pkgCache::DepIterator Start; + unsigned long LastIndex; + unsigned long Len; + + RDepListStruct(pkgCache::DepIterator const &I) : Iter(I), Start(I), + LastIndex(0) + { + Len = 0; + pkgCache::DepIterator D = I; + for (; D.end() == false; D++) + Len++; + } + RDepListStruct() {abort();}; // G++ Bug.. +}; + +static PyObject *CreateProvides(PyObject *Owner,pkgCache::PrvIterator I) +{ + PyObject *List = PyList_New(0); + for (; I.end() == false; I++) + { + PyObject *Obj; + PyObject *Ver; + Ver = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type, + I.OwnerVer()); + Obj = Py_BuildValue("ssN",I.ParentPkg().Name(),I.ProvideVersion(), + Ver); + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} + +// Cache Class /*{{{*/ +// --------------------------------------------------------------------- + +static const char *cache_update_doc = + "update(progress, sources: SourceList, pulse_interval: int) -> bool\n\n" + "Update the index files used by the cache. A call to this method\n" + "does not affect the current Cache object; instead, a new one\n" + "should be created in order to use the changed index files.\n\n" + "The parameter 'progress' can be used to specify an\n" + "apt.progress.base.AcquireProgress() object , which will report\n" + "progress information while the index files are being fetched.\n" + "The parameter 'sources', if provided, is an apt_pkg.SourcesList\n" + "object listing the remote repositories to be used.\n" + "The 'pulse_interval' parameter indicates how long (in microseconds)\n" + "to wait between calls to the pulse() method of the 'progress' object.\n" + "The default is 500000 microseconds."; +static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args) +{ + PyObject *pyFetchProgressInst = 0; + PyObject *pySourcesList = 0; + int pulseInterval = 0; + if (PyArg_ParseTuple(Args, "OO!|i", &pyFetchProgressInst, + &PySourceList_Type, &pySourcesList, &pulseInterval) == 0) + return 0; + + PyFetchProgress progress; + progress.setCallbackInst(pyFetchProgressInst); + pkgSourceList *source = GetCpp<pkgSourceList*>(pySourcesList); + bool res = ListUpdate(progress, *source, pulseInterval); + + PyObject *PyRes = PyBool_FromLong(res); + return HandleErrors(PyRes); +} + + +static PyMethodDef PkgCacheMethods[] = +{ + {"update",PkgCacheUpdate,METH_VARARGS,cache_update_doc}, + {} +}; + +static PyObject *PkgCacheGetGroupCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return MkPyNumber(Cache->HeaderP->GroupCount); +} + +static PyObject *PkgCacheGetGroups(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return CppPyObject_NEW<GrpListStruct>(Self,&PyGroupList_Type,Cache->GrpBegin()); +} + +static PyObject *PkgCacheGetPolicy(PyObject *Self, void*) { + PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); + pkgCacheFile *CacheF = GetCpp<pkgCacheFile*>(CacheFilePy); + pkgDepCache *DepCache = (pkgDepCache *)(*CacheF); + + pkgPolicy *Policy = (pkgPolicy *)&DepCache->GetPolicy(); + CppPyObject<pkgPolicy*> *PyPolicy = + CppPyObject_NEW<pkgPolicy*>(Self,&PyPolicy_Type,Policy); + // Policy should not be deleted, it is managed by CacheFile. + PyPolicy->NoDelete = true; + return PyPolicy; +} + +static PyObject *PkgCacheGetPackages(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return CppPyObject_NEW<PkgListStruct>(Self,&PyPackageList_Type,Cache->PkgBegin()); +} + +static PyObject *PkgCacheGetPackageCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return MkPyNumber((int)Cache->HeaderP->PackageCount); +} + +static PyObject *PkgCacheGetVersionCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return MkPyNumber(Cache->HeaderP->VersionCount); +} +static PyObject *PkgCacheGetDependsCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return MkPyNumber(Cache->HeaderP->DependsCount); +} + +static PyObject *PkgCacheGetPackageFileCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return MkPyNumber(Cache->HeaderP->PackageFileCount); +} + +static PyObject *PkgCacheGetVerFileCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return MkPyNumber(Cache->HeaderP->VerFileCount); +} + +static PyObject *PkgCacheGetProvidesCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return MkPyNumber(Cache->HeaderP->ProvidesCount); +} + +static PyObject *PkgCacheGetFileList(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + PyObject *List = PyList_New(0); + for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I.end() == false; I++) + { + PyObject *Obj; + Obj = CppPyObject_NEW<pkgCache::PkgFileIterator>(Self,&PyPackageFile_Type,I); + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} + +static PyObject *PkgCacheGetIsMultiArch(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return PyBool_FromLong(Cache->MultiArchCache()); +} + +static PyGetSetDef PkgCacheGetSet[] = { + {"depends_count",PkgCacheGetDependsCount,0, + "The number of apt_pkg.Dependency objects stored in the cache."}, + {"file_list",PkgCacheGetFileList,0, + "A list of apt_pkg.PackageFile objects stored in the cache."}, + {"group_count",PkgCacheGetGroupCount,0, + "The number of apt_pkg.Group objects stored in the cache."}, + {"groups", PkgCacheGetGroups, 0, "A list of Group objects in the cache"}, + {"policy", PkgCacheGetPolicy, 0, "The PkgPolicy for the cache"}, + {"is_multi_arch", PkgCacheGetIsMultiArch, 0, + "Whether the cache supports multi-arch."}, + {"package_count",PkgCacheGetPackageCount,0, + "The number of apt_pkg.Package objects stored in the cache."}, + {"package_file_count",PkgCacheGetPackageFileCount,0, + "The number of apt_pkg.PackageFile objects stored in the cache."}, + {"packages",PkgCacheGetPackages,0, + "A list of apt_pkg.Package objects stored in the cache."}, + {"provides_count",PkgCacheGetProvidesCount,0, + "Number of Provides relations described in the cache."}, + {"ver_file_count",PkgCacheGetVerFileCount,0, + "The number of (Version, PackageFile) relations."}, + {"version_count",PkgCacheGetVersionCount,0, + "The number of apt_pkg.Version objects stored in the cache."}, + {} +}; + +// Helper to call FindPkg(name) or FindPkg(name, architecture) +static pkgCache::PkgIterator CacheFindPkg(PyObject *self, PyObject *arg) +{ + const char *name; + const char *architecture; + pkgCache *cache = GetCpp<pkgCache *>(self); + + name = PyObject_AsString(arg); + + if (name != NULL) + return cache->FindPkg(name); + + PyErr_Clear(); + + if (PyArg_ParseTuple(arg, "ss", &name, &architecture) == 0) { + PyErr_Clear(); + PyErr_Format(PyExc_TypeError, "Expected a string or a pair of strings"); + return pkgCache::PkgIterator(); + } + + return cache->FindPkg(name, architecture); +} + +// Map access, operator [] +static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) +{ + pkgCache::PkgIterator Pkg = CacheFindPkg(Self, Arg); + if (Pkg.end() == true) + { + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError,Arg); + return 0; + } + + return CppPyObject_NEW<pkgCache::PkgIterator>(Self,&PyPackage_Type,Pkg); +} + +// Check whether the cache contains a package with a given name. +static int CacheContains(PyObject *Self,PyObject *Arg) +{ + bool res = (CacheFindPkg(Self, Arg).end() == false); + PyErr_Clear(); + return res; +} + +static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) +{ + PyObject *pyCallbackInst = 0; + char *kwlist[] = {"progress", 0}; + + if (PyArg_ParseTupleAndKeywords(Args, kwds, "|O", kwlist, + &pyCallbackInst) == 0) + return 0; + + if (_system == 0) { + PyErr_SetString(PyExc_ValueError,"_system not initialized"); + return 0; + } + + pkgCacheFile *Cache = new pkgCacheFile(); + + if (pyCallbackInst == Py_None) { + OpProgress Prog; + if (Cache->Open(&Prog,false) == false) + return HandleErrors(); + } else if(pyCallbackInst != 0) { + // sanity check for the progress object, see #497049 + if (PyObject_HasAttrString(pyCallbackInst, "done") != true) { + PyErr_SetString(PyExc_ValueError, + "OpProgress object must implement done()"); + return 0; + } + if (PyObject_HasAttrString(pyCallbackInst, "update") != true) { + PyErr_SetString(PyExc_ValueError, + "OpProgress object must implement update()"); + return 0; + } + PyOpProgress progress; + progress.setCallbackInst(pyCallbackInst); + if (Cache->Open(&progress,false) == false) + return HandleErrors(); + } + else { + OpTextProgress Prog; + if (Cache->Open(&Prog,false) == false) + return HandleErrors(); + } + + // ensure that the states are correct (LP: #659438) + pkgApplyStatus(*Cache); + + CppPyObject<pkgCacheFile*> *CacheFileObj = + CppPyObject_NEW<pkgCacheFile*>(0,&PyCacheFile_Type, Cache); + + CppPyObject<pkgCache *> *CacheObj = + CppPyObject_NEW<pkgCache *>(CacheFileObj,type, + (pkgCache *)(*Cache)); + + // Do not delete the pointer to the pkgCache, it is managed by pkgCacheFile. + CacheObj->NoDelete = true; + Py_DECREF(CacheFileObj); + return CacheObj; +} + +static Py_ssize_t CacheMapLen(PyObject *Self) +{ + return GetCpp<pkgCache*>(Self)->HeaderP->PackageCount; +} + +static char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n" + "The APT cache file contains a hash table mapping names of binary\n" + "packages to their metadata. A Cache object is the in-core\n" + "representation of the same. It provides access to APT’s idea of the\n" + "list of available packages.\n" + "The optional parameter *progress* can be used to specify an \n" + "apt.progress.base.OpProgress() object (or similar) which reports\n" + "progress information while the cache is being opened. If this\n" + "parameter is not supplied, the progress will be reported in simple,\n" + "human-readable text to standard output. If it is None, no output\n" + "will be made.\n\n" + "The cache can be used like a mapping from package names to Package\n" + "objects (although only getting items is supported). Instead of a name,\n" + "a tuple of a name and an architecture may be used."; +static PySequenceMethods CacheSeq = {0,0,0,0,0,0,0,CacheContains,0,0}; +static PyMappingMethods CacheMap = {CacheMapLen,CacheMapOp,0}; +PyTypeObject PyCache_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Cache", // tp_name + sizeof(CppPyObject<pkgCache *>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDeallocPtr<pkgCache *>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &CacheSeq, // tp_as_sequence + &CacheMap, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + _PyAptObject_getattro, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC), + doc_PkgCache, // tp_doc + CppTraverse<pkgCache *>, // tp_traverse + CppClear<pkgCache *>, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + PkgCacheMethods, // tp_methods + 0, // tp_members + PkgCacheGetSet, // 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 + PkgCacheNew, // tp_new +}; + /*}}}*/ +// PkgCacheFile Class /*{{{*/ +// --------------------------------------------------------------------- +PyTypeObject PyCacheFile_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "pkgCacheFile", // tp_name + sizeof(CppPyObject<pkgCacheFile*>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDeallocPtr<pkgCacheFile*>, // 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 +}; + +// Package List Class /*{{{*/ +// --------------------------------------------------------------------- +static Py_ssize_t PkgListLen(PyObject *Self) +{ + return GetCpp<PkgListStruct>(Self).Iter.Cache()->HeaderP->PackageCount; +} + +static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index) +{ + PkgListStruct &Self = GetCpp<PkgListStruct>(iSelf); + + if (!Self.move(Index)) + return 0; + return CppPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PyPackage_Type, + Self.Iter); +} + +static PySequenceMethods PkgListSeq = +{ + PkgListLen, + 0, // concat + 0, // repeat + PkgListItem, + 0, // slice + 0, // assign item + 0 // assign slice +}; + +static const char *packagelist_doc = + "A PackageList is an internally used structure to represent\n" + "the 'packages' attribute of apt_pkg.Cache objects in a more\n" + "efficient manner by creating Package objects only when they\n" + "are accessed."; + +PyTypeObject PyPackageList_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageList", // tp_name + sizeof(CppPyObject<PkgListStruct>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<PkgListStruct>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &PkgListSeq, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + packagelist_doc, // tp_doc + CppTraverse<PkgListStruct>, // tp_traverse + CppClear<PkgListStruct>, // tp_clear +}; + +/* The same for groups */ +static Py_ssize_t GrpListLen(PyObject *Self) +{ + return GetCpp<GrpListStruct>(Self).Iter.Cache()->HeaderP->GroupCount; +} + +static PyObject *GrpListItem(PyObject *iSelf,Py_ssize_t Index) +{ + GrpListStruct &Self = GetCpp<GrpListStruct>(iSelf); + + if (!Self.move(Index)) + return 0; + return CppPyObject_NEW<pkgCache::GrpIterator>(GetOwner<GrpListStruct>(iSelf),&PyGroup_Type, + Self.Iter); +} + +static PySequenceMethods GrpListSeq = +{ + GrpListLen, + 0, // concat + 0, // repeat + GrpListItem, + 0, // slice + 0, // assign item + 0 // assign slice +}; + +static const char *grouplist_doc = + "A GroupList is an internally used structure to represent\n" + "the 'groups' attribute of apt_pkg.Cache objects in a more\n" + "efficient manner by creating Group objects only when they\n" + "are accessed."; + +PyTypeObject PyGroupList_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.GroupList", // tp_name + sizeof(CppPyObject<GrpListStruct>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<GrpListStruct>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &GrpListSeq, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + grouplist_doc, // tp_doc + CppTraverse<GrpListStruct>, // tp_traverse + CppClear<GrpListStruct>, // tp_clear +}; + + +#define Owner (GetOwner<pkgCache::PkgIterator>(Self)) +#define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \ +{ \ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); \ + return Ret; \ +} + +MkGet(PackageGetName,CppPyString(Pkg.Name())) +MkGet(PackageGetArch,CppPyString(Pkg.Arch())) +MkGet(PackageGetRevDependsList,CppPyObject_NEW<RDepListStruct>(Owner, + &PyDependencyList_Type, Pkg.RevDependsList())) +MkGet(PackageGetProvidesList,CreateProvides(Owner,Pkg.ProvidesList())) +MkGet(PackageGetSelectedState,MkPyNumber(Pkg->SelectedState)) +MkGet(PackageGetInstState,MkPyNumber(Pkg->InstState)) +MkGet(PackageGetCurrentState,MkPyNumber(Pkg->CurrentState)) +MkGet(PackageGetID,MkPyNumber(Pkg->ID)) +# +MkGet(PackageGetEssential,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Essential) != 0)) +MkGet(PackageGetImportant,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Important) != 0)) +#undef MkGet +#undef Owner + +static const char PackageGetFullName_doc[] = + "get_fullname([pretty: bool = False]) -> str\n\n" + "Get the full name of the package, including the architecture. If\n" + "'pretty' is True, the architecture is omitted for native packages,\n" + "that is, and amd64 apt package on an amd64 system would give 'apt'."; +static PyObject *PackageGetFullName(PyObject *Self,PyObject *Args,PyObject *kwds) +{ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); + char pretty = 0; + char *kwlist[] = {"pretty", 0}; + + if (PyArg_ParseTupleAndKeywords(Args, kwds, "|b", kwlist, + &pretty) == 0) + return 0; + + + return CppPyString(Pkg.FullName(pretty)); +} + +static PyObject *PackageGetVersionList(PyObject *Self,void*) +{ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self); + + PyObject *List = PyList_New(0); + for (pkgCache::VerIterator I = Pkg.VersionList(); I.end() == false; I++) + { + PyObject *Obj; + Obj = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,I); + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} + +static PyObject *PackageGetHasVersions(PyObject *Self,void*) +{ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); + return PyBool_FromLong(Pkg.VersionList().end() == false); +} + +static PyObject *PackageGetHasProvides(PyObject *Self,void*) +{ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); + return PyBool_FromLong(Pkg.ProvidesList().end() == false); +} + +static PyObject *PackageGetCurrentVer(PyObject *Self,void*) +{ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self); + if (Pkg->CurrentVer == 0) + { + Py_INCREF(Py_None); + return Py_None; + } + return CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type, + Pkg.CurrentVer()); +} + + +static PyMethodDef PackageMethods[] = +{ + {"get_fullname",(PyCFunction)PackageGetFullName,METH_VARARGS|METH_KEYWORDS, + PackageGetFullName_doc}, + {} +}; + +static PyGetSetDef PackageGetSet[] = { + {"name",PackageGetName,0, + "The name of the package."}, + {"architecture",PackageGetArch,0, "The architecture of the package."}, + {"rev_depends_list",PackageGetRevDependsList,0, + "An apt_pkg.DependencyList object of all reverse dependencies."}, + {"provides_list",PackageGetProvidesList,0, + "A list of all packages providing this package. The list contains\n" + "tuples in the format (providesname, providesver, version)\n" + "where 'version' is an apt_pkg.Version object."}, + {"selected_state",PackageGetSelectedState,0, + "The state of the selection, which can be compared against the constants\n" + "SELSTATE_DEINSTALL, SELSTATE_HOLD, SELSTATE_INSTALL, SELSTATE_PURGE,\n" + "SELSTATE_UNKNOWN of the apt_pkg module."}, + {"inst_state",PackageGetInstState,0, + "The state of the install, which be compared against the constants\n" + "INSTSTATE_HOLD, INSTSTATE_HOLD_REINSTREQ, INSTSTATE_OK,\n" + "INSTSTATE_REINSTREQ of the apt_pkg module."}, + {"current_state",PackageGetCurrentState,0, + "The current state, which can be compared against the constants\n" + "CURSTATE_CONFIG_FILES, CURSTATE_HALF_CONFIGURED,\n" + "CURSTATE_HALF_INSTALLED, CURSTATE_INSTALLED, CURSTATE_NOT_INSTALLED,\n" + "CURSTATE_UNPACKED of the apt_pkg module."}, + {"id",PackageGetID,0, + "The numeric ID of the package"}, + {"essential",PackageGetEssential,0, + "Boolean value determining whether the package is essential."}, + {"important",PackageGetImportant,0, + "Boolean value determining whether the package has the 'important'\n" + "flag set ('Important: yes' in the Packages file). No longer used."}, + {"version_list",PackageGetVersionList,0, + "A list of all apt_pkg.Version objects for this package."}, + {"current_ver",PackageGetCurrentVer,0, + "The version of the package currently installed or None."}, + {"has_versions",PackageGetHasVersions,0, + "Whether the package has at least one version in the cache."}, + {"has_provides",PackageGetHasProvides,0, + "Whether the package is provided by at least one other package."}, + {} +}; + +static PyObject *PackageRepr(PyObject *Self) +{ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); + return PyString_FromFormat("<%s object: name:'%s' id:%u>", Self->ob_type->tp_name, + Pkg.Name(), Pkg->ID); +} + +static const char *package_doc = + "Represent a package. A package is uniquely identified by its name\n" + "and each package can have zero or more versions which can be\n" + "accessed via the version_list property. Packages can be installed\n" + "and removed by apt_pkg.DepCache."; + +PyTypeObject PyPackage_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Package", // tp_name + sizeof(CppPyObject<pkgCache::PkgIterator>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<pkgCache::PkgIterator>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + PackageRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + _PyAptObject_getattro, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + package_doc, // tp_doc + CppTraverse<pkgCache::PkgIterator>, // tp_traverse + CppClear<pkgCache::PkgIterator>,// tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + PackageMethods, // tp_methods + 0, // tp_members + PackageGetSet, // tp_getset +}; + +#define Description_MkGet(PyFunc,Ret) static PyObject \ + *PyFunc(PyObject *Self,void*) { \ + pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); \ + return Ret; } + +Description_MkGet(DescriptionGetLanguageCode, + CppPyString(Desc.LanguageCode())) +Description_MkGet(DescriptionGetMd5,CppPyString(Desc.md5())) +#undef Description_MkGet + +static PyObject *DescriptionGetFileList(PyObject *Self,void*) +{ + pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::DescIterator>(Self); + + /* The second value in the tuple is the index of the VF item. If the + user wants to request a lookup then that number will be used. + Maybe later it can become an object. */ + PyObject *List = PyList_New(0); + for (pkgCache::DescFileIterator I = Desc.FileList(); I.end() == false; I++) + { + PyObject *DescFile; + PyObject *Obj; + DescFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File()); + Obj = Py_BuildValue("NN",DescFile,MkPyNumber(I.Index())); + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} + +static PyGetSetDef DescriptionGetSet[] = { + {"language_code",DescriptionGetLanguageCode,0, + "The language code of the description. Empty string for untranslated\n" + "descriptions."}, + {"md5",DescriptionGetMd5,0, + "The MD5 hash of the description."}, + {"file_list",DescriptionGetFileList,0, + "A list of all apt_pkg.PackageFile objects related to this description."}, + {} +}; + +static PyObject *DescriptionRepr(PyObject *Self) +{ + pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); + return PyString_FromFormat("<%s object: language_code:'%s' md5:'%s' ", + Self->ob_type->tp_name, Desc.LanguageCode(), + Desc.md5()); +} + +static const char *description_doc = + "Represent a package description and some attributes. Needed for\n" + "things like translated descriptions."; + +PyTypeObject PyDescription_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Description", // tp_name + sizeof(CppPyObject<pkgCache::DescIterator>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<pkgCache::DescIterator>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + DescriptionRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + _PyAptObject_getattro, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + description_doc, // tp_doc + CppTraverse<pkgCache::DescIterator>, // tp_traverse + CppClear<pkgCache::DescIterator>,// tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + DescriptionGetSet, // tp_getset +}; + /*}}}*/ +// Version Class /*{{{*/ +// --------------------------------------------------------------------- + +/* This is the simple depends result, the elements are split like + ParseDepends does */ +static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, + bool AsObj) +{ + PyObject *Dict = PyDict_New(); + PyObject *LastDep = 0; + unsigned LastDepType = 0; + for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) + { + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); + + // Switch/create a new dict entry + if (LastDepType != Start->Type || LastDep != 0) + { + PyObject *Dep = CppPyString(UntranslatedDepTypes[Start->Type]); + LastDepType = Start->Type; + LastDep = PyDict_GetItem(Dict,Dep); + if (LastDep == 0) + { + LastDep = PyList_New(0); + PyDict_SetItem(Dict,Dep,LastDep); + Py_DECREF(LastDep); + } + Py_DECREF(Dep); + } + + PyObject *OrGroup = PyList_New(0); + while (1) + { + PyObject *Obj; + if (AsObj == true) + Obj = CppPyObject_NEW<pkgCache::DepIterator>(Owner,&PyDependency_Type, + Start); + else + { + if (Start->Version == 0) + Obj = Py_BuildValue("sss", + Start.TargetPkg().Name(), + "", + Start.CompType()); + else + Obj = Py_BuildValue("sss", + Start.TargetPkg().Name(), + Start.TargetVer(), + Start.CompType()); + } + PyList_Append(OrGroup,Obj); + Py_DECREF(Obj); + + if (Start == End) + break; + Start++; + } + + PyList_Append(LastDep,OrGroup); + Py_DECREF(OrGroup); + } + + return Dict; +} + +static inline pkgCache::VerIterator Version_GetVer(PyObject *Self) { + return GetCpp<pkgCache::VerIterator>(Self); +} + +// Version attributes. +static PyObject *VersionGetVerStr(PyObject *Self, void*) { + return CppPyString(Version_GetVer(Self).VerStr()); +} +static PyObject *VersionGetSection(PyObject *Self, void*) { + return CppPyString(Version_GetVer(Self).Section()); +} +static PyObject *VersionGetArch(PyObject *Self, void*) { + return CppPyString(Version_GetVer(Self).Arch()); +} +static PyObject *VersionGetFileList(PyObject *Self, void*) { + pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); + PyObject *List = PyList_New(0); + for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; I++) + { + PyObject *PkgFile; + PyObject *Obj; + PkgFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File()); + Obj = Py_BuildValue("NN",PkgFile,MkPyNumber(I.Index())); + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} + +static PyObject *VersionGetDependsListStr(PyObject *Self, void*) { + pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); + return MakeDepends(Owner,Ver,false); +} +static PyObject *VersionGetDependsList(PyObject *Self, void*) { + pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); + return MakeDepends(Owner,Ver,true); +} +static PyObject *VersionGetParentPkg(PyObject *Self, void*) { + PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); + return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type, + Version_GetVer(Self).ParentPkg()); +} +static PyObject *VersionGetProvidesList(PyObject *Self, void*) { + PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); + return CreateProvides(Owner,Version_GetVer(Self).ProvidesList()); +} +static PyObject *VersionGetSize(PyObject *Self, void*) { + return MkPyNumber(Version_GetVer(Self)->Size); +} +static PyObject *VersionGetInstalledSize(PyObject *Self, void*) { + return MkPyNumber(Version_GetVer(Self)->InstalledSize); +} +static PyObject *VersionGetHash(PyObject *Self, void*) { + return MkPyNumber(Version_GetVer(Self)->Hash); +} +static PyObject *VersionGetID(PyObject *Self, void*) { + return MkPyNumber(Version_GetVer(Self)->ID); +} +static PyObject *VersionGetPriority(PyObject *Self, void*) { + return MkPyNumber(Version_GetVer(Self)->Priority); +} +static PyObject *VersionGetPriorityStr(PyObject *Self, void*) { + return CppPyString(Version_GetVer(Self).PriorityType()); +} +static PyObject *VersionGetDownloadable(PyObject *Self, void*) { + return PyBool_FromLong(Version_GetVer(Self).Downloadable()); +} +static PyObject *VersionGetTranslatedDescription(PyObject *Self, void*) { + pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); + return CppPyObject_NEW<pkgCache::DescIterator>(Owner, + &PyDescription_Type, + Ver.TranslatedDescription()); +} + +static PyObject *VersionGetIsSecurityUpdate(PyObject *Self, void*) { + return PyBool_FromLong(Version_GetVer(Self).IsSecurityUpdate()); +} + +static PyObject *VersionGetMultiArch(PyObject *Self, void*) +{ + return MkPyNumber(Version_GetVer(Self)->MultiArch); +} + +#if 0 // FIXME: enable once pkgSourceList is stored somewhere +static PyObject *VersionGetIsTrusted(PyObject *Self, void*) { + else if (strcmp("IsTrusted", Name) == 0) + { + pkgSourceList Sources; + Sources.ReadMainList(); + for(pkgCache::VerFileIterator i = Ver.FileList(); !i.end(); i++) + { + pkgIndexFile *index; + if(Sources.FindIndex(i.File(), index) && !index->IsTrusted()) + Py_RETURN_FALSE; + } + Py_RETURN_TRUE; + } +} +#endif + +#define NOTNULL(x) (x ? x : "") + +static PyObject *VersionRepr(PyObject *Self) +{ + pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); + 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(), + NOTNULL(Ver.Section()), NOTNULL(Ver.Arch()), + (unsigned long)Ver->Size, + (unsigned long)Ver->InstalledSize, + Ver->Hash, Ver->ID, Ver->Priority); +} +#undef NOTNULL + +static PyObject *version_richcompare(PyObject *obj1, PyObject *obj2, int op) +{ + if (!PyVersion_Check(obj2)) + return Py_INCREF(Py_NotImplemented), Py_NotImplemented; + + const pkgCache::VerIterator &a = GetCpp<pkgCache::VerIterator>(obj1); + const pkgCache::VerIterator &b = GetCpp<pkgCache::VerIterator>(obj2); + const int comparison = _system->VS->CmpVersion(a.VerStr(), b.VerStr()); + switch (op) { + case Py_LT: return PyBool_FromLong(comparison < 0); + case Py_LE: return PyBool_FromLong(comparison <= 0); + case Py_EQ: return PyBool_FromLong(comparison == 0); + case Py_NE: return PyBool_FromLong(comparison != 0); + case Py_GE: return PyBool_FromLong(comparison >= 0); + case Py_GT: return PyBool_FromLong(comparison > 0); + default: return NULL; // should not happen. + } +} + +static PyGetSetDef VersionGetSet[] = { + {"arch",VersionGetArch,0, + "The architecture of this specific version of the package."}, + {"depends_list",VersionGetDependsList,0, + "A dictionary mapping dependency types to lists (A) of lists (B) of\n" + "apt_pkg.Dependency objects. The lists (B) represent or dependencies\n" + "like 'a || b'."}, + {"depends_list_str",VersionGetDependsListStr,0, + "Same as depends_list, except that the apt_pkg.Dependency objects\n" + "are 3-tuples of the form (name, version, operator); where operator\n" + "is one of '<', '<=', '=', '>=', '>'."}, + {"downloadable",VersionGetDownloadable,0, + "Whether the version can be downloaded."}, + {"file_list",VersionGetFileList,0, + "A list of tuples (packagefile: apt_pkg.PackageFile, index: int) for the\n" + "PackageFile objects related to this package. The index can be used\n" + "to retrieve the record of this package version."}, + {"hash",VersionGetHash,0, + "The numeric hash of the version used in the internal storage."}, + {"id",VersionGetID,0, + "The numeric ID of the package."}, + {"installed_size",VersionGetInstalledSize,0, + "The installed size of this package version."}, + {"multi_arch",VersionGetMultiArch,0, + "Multi-arch state of this package, as an integer. See\n" + "the various MULTI_ARCH_* members."}, + {"parent_pkg",VersionGetParentPkg,0, + "The parent package of this version."}, + {"priority",VersionGetPriority,0, + "The priority of the package as an integer, which can be compared to\n" + "the constants PRI_EXTRA, PRI_IMPORTANT, PRI_OPTIONAL, PRI_REQUIRED,\n" + "PRI_STANDARD of the apt_pkg module."}, + {"priority_str",VersionGetPriorityStr,0, + "The priority of the package, as a string."}, + {"provides_list",VersionGetProvidesList,0, + "A list of all packages provided by this version. The list contains\n" + "tuples in the format (providesname, providesver, version)\n" + "where 'version' is an apt_pkg.Version object."}, + {"section",VersionGetSection,0, + "The section of this package version."}, + {"size",VersionGetSize,0, + "The size of the package file."}, + {"translated_description",VersionGetTranslatedDescription,0, + "An apt_pkg.Description object for the translated description if\n" + "available or the untranslated fallback."}, + {"is_security_update",VersionGetIsSecurityUpdate,0, + "Whether this version is a security update."}, + {"ver_str",VersionGetVerStr,0, + "The version string."}, + {} +}; + +PyTypeObject PyVersion_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Version", // tp_name + sizeof(CppPyObject<pkgCache::VerIterator>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<pkgCache::VerIterator>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + VersionRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + _PyAptObject_getattro, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + "Version Object", // tp_doc + CppTraverse<pkgCache::VerIterator>, // tp_traverse + CppClear<pkgCache::VerIterator>,// tp_clear + version_richcompare, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + VersionGetSet, // tp_getset +}; + + /*}}}*/ + +// PackageFile Class /*{{{*/ +// --------------------------------------------------------------------- +static PyObject *PackageFile_GetFileName(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyPath(File.FileName()); +} + +static PyObject *PackageFile_GetArchive(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Archive()); +} + +static PyObject *PackageFile_GetComponent(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Component()); +} + +static PyObject *PackageFile_GetVersion(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Version()); +} + +static PyObject *PackageFile_GetOrigin(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Origin()); +} + +static PyObject *PackageFile_GetLabel(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Label()); +} + +static PyObject *PackageFile_GetArchitecture(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Architecture()); +} + +static PyObject *PackageFile_GetCodename(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Codename()); +} + +static PyObject *PackageFile_GetSite(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.Site()); +} + +static PyObject *PackageFile_GetIndexType(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return CppPyString(File.IndexType()); +} +static PyObject *PackageFile_GetSize(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return MkPyNumber(File->Size); +} + +static PyObject *PackageFile_GetNotSource(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return PyBool_FromLong((File->Flags & pkgCache::Flag::NotSource) != 0); +} +static PyObject *PackageFile_GetNotAutomatic(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return PyBool_FromLong((File->Flags & pkgCache::Flag::NotAutomatic) != 0); +} + +static PyObject *PackageFile_GetID(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return MkPyNumber(File->ID); +} + +#define S(s) (s == NULL ? "" : s) +static PyObject *PackageFileRepr(PyObject *Self) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + + 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[] = { + {"architecture",PackageFile_GetArchitecture,0, + "The architecture of the package file. Unused, empty string nowadays."}, + {"archive",PackageFile_GetArchive,0, + "The archive of the package file (i.e. 'Suite' in the Release file)."}, + {"component",PackageFile_GetComponent,0, + "The component of this package file (e.g. 'main')."}, + {"codename",PackageFile_GetCodename,0, + "The codename of this package file (e.g. squeeze-updates)."}, + {"filename",PackageFile_GetFileName,0, + "The path to the file."}, + {"id",PackageFile_GetID,0, + "The numeric ID of this PackageFile object."}, + {"index_type",PackageFile_GetIndexType,0, + "A string describing the type of index. Known values are\n" + "'Debian Package Index', 'Debian Translation Index', and\n" + "'Debian dpkg status file'."}, + {"label",PackageFile_GetLabel,0, + "The label set in the release file (e.g. 'Debian')."}, + {"not_automatic",PackageFile_GetNotAutomatic,0, + "Whether the NotAutomatic flag is set in the Release file."}, + {"not_source",PackageFile_GetNotSource,0, + "Whether this package file lacks an active (sources.list) source;" + "packages listed in such a file cannot be downloaded."}, + {"origin",PackageFile_GetOrigin,0, + "The origin set in the release file."}, + {"site",PackageFile_GetSite,0, + "The hostname of the location this file comes from."}, + {"size",PackageFile_GetSize,0, + "The size of the file."}, + {"version",PackageFile_GetVersion,0, + "The version set in the release file (e.g. '5.0.X' for lenny, where X\n" + "is a point release)."}, + {} +}; + +static const char *packagefile_doc = + "A package file is an index file stored in the cache with some\n" + "additional pieces of information."; + +PyTypeObject PyPackageFile_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageFile", // tp_name + sizeof(CppPyObject<pkgCache::PkgFileIterator>), // tp_basicsize + 0, // tp_itemsize + CppDealloc<pkgCache::PkgFileIterator>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + PackageFileRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + _PyAptObject_getattro, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + packagefile_doc, // tp_doc + CppTraverse<pkgCache::PkgFileIterator>, // tp_traverse + CppClear<pkgCache::PkgFileIterator>, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + PackageFileGetSet, // tp_getset +}; + +// depends class +static PyObject *DependencyRepr(PyObject *Self) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + + 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 *DepAllTargets(PyObject *Self,PyObject *Args) +{ + if (PyArg_ParseTuple(Args,"") == 0) + return 0; + + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); + + std::unique_ptr<pkgCache::Version *[]> Vers(Dep.AllTargets()); + PyObject *List = PyList_New(0); + for (pkgCache::Version **I = Vers.get(); *I != 0; I++) + { + PyObject *Obj; + Obj = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type, + pkgCache::VerIterator(*Dep.Cache(),*I)); + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} + +static PyMethodDef DependencyMethods[] = +{ + {"all_targets",DepAllTargets,METH_VARARGS, + "all_targets() -> list\n\n" + "A list of all possible apt_pkg.Version objects which satisfy this\n" + "dependency."}, + {} +}; + +// Dependency Class /*{{{*/ +// --------------------------------------------------------------------- + +static PyObject *DependencyGetTargetVer(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + if (Dep->Version == 0) + return CppPyString(""); + return CppPyString(Dep.TargetVer()); +} + +static PyObject *DependencyGetTargetPkg(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); + return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type, + Dep.TargetPkg()); +} + +static PyObject *DependencyGetParentVer(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); + return CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type, + Dep.ParentVer()); +} + +static PyObject *DependencyGetParentPkg(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); + return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type, + Dep.ParentPkg()); +} + +static PyObject *DependencyGetCompType(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return CppPyString(Dep.CompType()); +} + +static PyObject *DependencyGetCompTypeDeb(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return CppPyString(pkgCache::CompTypeDeb(Dep->CompareOp)); +} + +static PyObject *DependencyGetDepType(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return CppPyString(Dep.DepType()); +} + +static PyObject *DependencyGetDepTypeUntranslated(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return CppPyString(UntranslatedDepTypes[Dep->Type]); +} + +static PyObject *DependencyGetDepTypeEnum(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return MkPyNumber(Dep->Type); +} + +static PyObject *DependencyGetID(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return MkPyNumber(Dep->ID); +} + +static PyGetSetDef DependencyGetSet[] = { + {"comp_type",DependencyGetCompType,0, + "The type of comparison in mathematical notation, as a string, namely one " + "of:\n" + "'<', '<=', '=', '!=', '>=', '>', ''.\n" + "The empty string will be returned in case of an unversioned dependency."}, + {"comp_type_deb",DependencyGetCompTypeDeb,0, + "The type of comparison in Debian notation, as a string, namely one of:\n" + "'<<', '<=', '=', '!=', '>=', '>>', ''.\n" + "The empty string will be returned in case of an unversioned dependency.\n" + "For details see the Debian Policy Manual on the syntax of relationship " + "fields:\n" + "https://www.debian.org/doc/debian-policy/ch-relationships.html#s-depsyntax"}, + {"dep_type",DependencyGetDepType,0, + "The type of the dependency; may be translated"}, + {"dep_type_untranslated",DependencyGetDepTypeUntranslated,0, + "Same as dep_type, but guaranteed to be untranslated."}, + {"dep_type_enum",DependencyGetDepTypeEnum,0, + "Same as dep_type, but with a numeric value instead of a string. Can\n" + "be compared against the TYPE_ constants defined in this class."}, + {"id",DependencyGetID,0, + "The numeric ID of this dependency object."}, + {"parent_pkg",DependencyGetParentPkg,0, + "The apt_pkg.Package object of the package which depends."}, + {"parent_ver",DependencyGetParentVer,0, + "The apt_pkg.Version object of the package which depends."}, + {"target_pkg",DependencyGetTargetPkg,0, + "The apt_pkg.Package object of the package depended upon"}, + {"target_ver",DependencyGetTargetVer,0, + "The version of the package depended upon as a string"}, + {} +}; + +static const char *dependency_doc = + "Represent a dependency from one package version to a package,\n" + "and (optionally) a version relation (e.g. >= 1). Dependency\n" + "objects also provide useful functions like all_targets()\n" + "for selecting packages to satisfy the dependency."; + +PyTypeObject PyDependency_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Dependency", // tp_name + sizeof(CppPyObject<pkgCache::DepIterator>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<pkgCache::DepIterator>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + DependencyRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + _PyAptObject_getattro, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + dependency_doc, // tp_doc + CppTraverse<pkgCache::DepIterator>, // tp_traverse + CppClear<pkgCache::DepIterator>, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + DependencyMethods, // tp_methods + 0, // tp_members + DependencyGetSet, // tp_getset +}; + + /*}}}*/ + /*}}}*/ +// Reverse Dependency List Class /*{{{*/ +// --------------------------------------------------------------------- +static Py_ssize_t RDepListLen(PyObject *Self) +{ + return GetCpp<RDepListStruct>(Self).Len; +} + +static PyObject *RDepListItem(PyObject *iSelf,Py_ssize_t Index) +{ + RDepListStruct &Self = GetCpp<RDepListStruct>(iSelf); + if (Index < 0 || (unsigned)Index >= Self.Len) + { + PyErr_SetNone(PyExc_IndexError); + return 0; + } + + if ((unsigned)Index < Self.LastIndex) + { + Self.LastIndex = 0; + Self.Iter = Self.Start; + } + + while ((unsigned)Index > Self.LastIndex) + { + Self.LastIndex++; + Self.Iter++; + if (Self.Iter.end() == true) + { + PyErr_SetNone(PyExc_IndexError); + return 0; + } + } + + return CppPyObject_NEW<pkgCache::DepIterator>(GetOwner<RDepListStruct>(iSelf), + &PyDependency_Type,Self.Iter); +} + +static PySequenceMethods RDepListSeq = +{ + RDepListLen, + 0, // concat + 0, // repeat + RDepListItem, + 0, // slice + 0, // assign item + 0 // assign slice +}; + +static const char *dependencylist_doc = + "A simple list-like type for representing multiple dependency\n" + "objects in an efficient manner; without having to generate\n" + "all Dependency objects in advance."; +PyTypeObject PyDependencyList_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.DependencyList", // tp_name + sizeof(CppPyObject<RDepListStruct>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDealloc<RDepListStruct>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &RDepListSeq, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + dependencylist_doc, // tp_doc + CppTraverse<RDepListStruct>, // tp_traverse + CppClear<RDepListStruct>, // tp_clear +}; + + /*}}}*/ + + |