summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/control9
-rw-r--r--debian/python-apt.dirs1
-rwxr-xr-xdebian/rules23
-rwxr-xr-xdoc/examples/config.py55
-rwxr-xr-xdoc/examples/configisc.py39
-rwxr-xr-xdoc/examples/tagfile.py8
-rwxr-xr-xdoc/examples/versiontest.py36
-rw-r--r--python/apt_instmodule.cc83
-rw-r--r--python/apt_pkgmodule.cc357
-rw-r--r--python/apt_pkgmodule.h65
-rw-r--r--python/cache.cc731
-rw-r--r--python/configuration.cc523
-rw-r--r--python/generic.cc86
-rw-r--r--python/generic.h132
-rw-r--r--python/makefile21
-rw-r--r--python/pkgrecords.cc119
-rw-r--r--python/string.cc96
-rw-r--r--python/tag.cc445
18 files changed, 2829 insertions, 0 deletions
diff --git a/debian/control b/debian/control
new file mode 100644
index 00000000..7463bc9c
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,9 @@
+Package: python-apt
+Architecture: any
+Depends: ${shlibs:Depends}
+Priority: optional
+Description: Python interface to libapt-pkg
+ The apt-pkg Python interface will provide full access to the internal
+ libapt-pkg structures allowing Python programs to easially perform a
+ variety of functions.
+
diff --git a/debian/python-apt.dirs b/debian/python-apt.dirs
new file mode 100644
index 00000000..621814df
--- /dev/null
+++ b/debian/python-apt.dirs
@@ -0,0 +1 @@
+usr/lib/python1.5/site-packages
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 00000000..a6919824
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,23 @@
+
+python-apt: build debian/shlibs.local
+ dh_testdir -p$@
+ dh_testroot -p$@
+ dh_clean -p$@ -k
+ dh_installdirs -p$@
+
+ # install the modules
+ cp $(BLD)/bin/apt_pkgmodule.so $(BLD)/bin/apt_instmodule.so debian/$@/usr/lib/python$(PYTHONVER)/site-packages/
+
+ dh_installdocs -p$@
+ dh_installexamples -p$@ $(BLD)/docs/examples/python/*
+
+ dh_installchangelogs -p$@
+ dh_strip -p$@
+ dh_compress -p$@
+ dh_fixperms -p$@
+ dh_installdeb -p$@
+ LD_LIBRARY_PATH=`pwd`/debian/tmp/usr/lib:`pwd`/debian/apt-utils/usr/lib dh_shlibdeps -p$@
+ dh_gencontrol -p$@
+ dh_md5sums -p$@
+ dh_builddeb -p$@
+
diff --git a/doc/examples/config.py b/doc/examples/config.py
new file mode 100755
index 00000000..222c1331
--- /dev/null
+++ b/doc/examples/config.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+# Example demonstrating how to use the configuration/commandline system
+# for configuration.
+# Some valid command lines..
+# config.py -h --help ; Turn on help
+# config.py -no-h --no-help --help=no ; Turn off help
+# config.py -qqq -q=3 ; verbosity to 3
+# config.py -c /etc/apt/apt.conf ; include that config file]
+# config.py -o help=true ; Turn on help by giving a config file string
+# config.py -no-h -- -help ; Turn off help, specify the file '-help'
+# -c and -o are standard APT-program options.
+
+# This shows how to use the system for configuration and option control.
+# The other varient is for ISC object config files. See configisc.py.
+import apt_pkg,sys,posixpath;
+
+# Create a new empty Configuration object - there is also the system global
+# configuration object apt_pkg.Config which is used interally by apt-pkg
+# routines to control unusual situations. I recommend using the sytem global
+# whenever possible..
+Cnf = apt_pkg.newConfiguration();
+
+print "Command line is",sys.argv
+
+# Load the default configuration file, InitConfig() does this better..
+Cnf.Set("config-file","/etc/apt/apt.conf"); # or Cnf["config-file"] = "..";
+if posixpath.exists(Cnf.FindFile("config-file")):
+ apt_pkg.ReadConfigFile(Cnf,"/etc/apt/apt.conf");
+
+# Merge the command line arguments into the configuration space
+Arguments = [('h',"help","help"),
+ ('v',"version","version"),
+ ('q',"quiet","quiet","IntLevel"),
+ ('c',"config-file","","ConfigFile"),
+ ('o',"option","","ArbItem")]
+print "FileNames",apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv);
+
+print "Quiet level selected is",Cnf.FindI("quiet",0);
+
+# Do some stuff with it
+if Cnf.FindB("version",0) == 1:
+ print "Version selected - 1.1";
+
+if Cnf.FindB("help",0) == 1:
+ print apt_pkg.Package,apt_pkg.Version,"for",apt_pkg.Architecture, \
+ "compiled on",apt_pkg.Date,apt_pkg.Time;
+ print "Hi, I am the help text for this program";
+ sys.exit(0);
+
+print "No help for you, try -h";
+
+# Print the configuration space
+print "The Configuration space looks like:";
+for I in Cnf.keys():
+ print "%s \"%s\";"%(I,Cnf[I]);
diff --git a/doc/examples/configisc.py b/doc/examples/configisc.py
new file mode 100755
index 00000000..1773a919
--- /dev/null
+++ b/doc/examples/configisc.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+# Example demonstrating how to use the configuration/commandline system
+# for object setup.
+
+# This parses the given config file in 'ISC' style where the sections
+# represent object instances and shows how to iterate over the sections.
+# Pass it the sample apt-ftparchive configuration,
+# doc/examples/ftp-archive.conf
+# or a bind8 config file..
+
+import apt_pkg,sys,posixpath;
+
+ConfigFile = apt_pkg.ParseCommandLine(apt_pkg.Config,[],sys.argv);
+
+if len(ConfigFile) != 1:
+ print "Must have exactly 1 file name";
+ sys.exit(0);
+
+Cnf = apt_pkg.newConfiguration();
+apt_pkg.ReadConfigFileISC(Cnf,ConfigFile[0]);
+
+# Print the configuration space
+#print "The Configuration space looks like:";
+#for I in Cnf.keys():
+# print "%s \"%s\";"%(I,Cnf[I]);
+
+# bind8 config file..
+if Cnf.has_key("Zone"):
+ print "Zones: ",Cnf.SubTree("zone").List();
+ for I in Cnf.List("zone"):
+ SubCnf = Cnf.SubTree(I);
+ if SubCnf.Find("type") == "slave":
+ print "Masters for %s: %s"%(SubCnf.MyTag(),SubCnf.ValueList("masters"));
+else:
+ print "Tree definitions:";
+ for I in Cnf.List("tree"):
+ SubCnf = Cnf.SubTree(I);
+ # This could use Find which would eliminate the possibility of exceptions.
+ print "Subtree %s with sections '%s' and architectures '%s'"%(SubCnf.MyTag(),SubCnf["Sections"],SubCnf["Architectures"]);
diff --git a/doc/examples/tagfile.py b/doc/examples/tagfile.py
new file mode 100755
index 00000000..01fed2cc
--- /dev/null
+++ b/doc/examples/tagfile.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+import apt_pkg
+
+Parse = apt_pkg.ParseTagFile(open("apt/lists/_org_ftp.debian.org_ftp_dists_potato_main_binary-i386_Packages","r"));
+
+while Parse.Step() == 1:
+ print Parse.Section.get("Package");
+ print apt_pkg.ParseDepends(Parse.Section.get("Depends",""));
diff --git a/doc/examples/versiontest.py b/doc/examples/versiontest.py
new file mode 100755
index 00000000..95f887f2
--- /dev/null
+++ b/doc/examples/versiontest.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+# This is a simple clone of tests/versiontest.cc
+import apt_pkg,sys,re,string;
+apt_pkg.InitConfig();
+apt_pkg.InitSystem();
+
+TestFile = apt_pkg.ParseCommandLine(apt_pkg.Config,[],sys.argv);
+if len(TestFile) != 1:
+ print "Must have exactly 1 file name";
+ sys.exit(0);
+
+# Go over the file..
+List = open(TestFile[0],"r");
+CurLine = 0;
+while(1):
+ Line = List.readline();
+ CurLine = CurLine + 1;
+ if Line == "":
+ break;
+ Line = string.strip(Line);
+ if len(Line) == 0 or Line[0] == '#':
+ continue;
+
+ Split = re.split("[ \n]",Line);
+
+ # Check forward
+ if apt_pkg.VersionCompare(Split[0],Split[1]) != int(Split[2]):
+ print "Comparision failed on line %u. '%s' ? '%s' %i != %i"%(CurLine,
+ Split[0],Split[1],apt_pkg.VersionCompare(Split[0],Split[1]),
+ int(Split[2]));
+ # Check reverse
+ if apt_pkg.VersionCompare(Split[1],Split[0]) != -1*int(Split[2]):
+ print "Comparision failed on line %u. '%s' ? '%s' %i != %i"%(CurLine,
+ Split[1],Split[0],apt_pkg.VersionCompare(Split[1],Split[0]),
+ -1*int(Split[2]));
diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc
new file mode 100644
index 00000000..519d4730
--- /dev/null
+++ b/python/apt_instmodule.cc
@@ -0,0 +1,83 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_instmodule.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ apt_intmodule - Top level for the python module. Create the internal
+ structures for the module in the interpriter.
+
+ Note, this module shares state (particularly global config) with the
+ apt_pkg module.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+
+#include <apt-pkg/debfile.h>
+#include <apt-pkg/error.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <python/Python.h>
+ /*}}}*/
+
+// debExtractControl - Exctract an arbitary control member /*{{{*/
+// ---------------------------------------------------------------------
+/* This is a common operation so this function will stay, but others that
+ expose the full range of the apt-inst .deb processing will join it some
+ day. */
+static char *doc_debExtractControl =
+"debExtractControl(File[,Member]) -> String\n"
+"Returns the indicated file from the control tar. The default is 'control'\n";
+static PyObject *debExtractControl(PyObject *Self,PyObject *Args)
+{
+ char *Member = "control";
+ PyObject *File;
+ if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Member) == 0)
+ return 0;
+
+ // Subscope makes sure any clean up errors are properly handled.
+ PyObject *Res = 0;
+ {
+ // Open the file and associate the .deb
+ FileFd Fd(fileno(PyFile_AsFile(File)),false);
+ debDebFile Deb(Fd);
+ if (_error->PendingError() == true)
+ return HandleErrors();
+
+ debDebFile::MemControlExtract Extract(Member);
+ if (Extract.Read(Deb) == false)
+ return HandleErrors();
+
+ // Build the return result
+
+ if (Extract.Control == 0)
+ {
+ Py_INCREF(Py_None);
+ Res = Py_None;
+ }
+ else
+ Res = PyString_FromStringAndSize(Extract.Control,Extract.Length+2);
+ }
+
+ return HandleErrors(Res);
+}
+ /*}}}*/
+
+// initapt_inst - Core Module Initialization /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static PyMethodDef methods[] =
+{
+ // Stuff
+ {"debExtractControl",debExtractControl,METH_VARARGS,doc_debExtractControl},
+
+ {}
+};
+
+extern "C" void initapt_inst()
+{
+ Py_InitModule("apt_inst",methods);
+}
+ /*}}}*/
diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc
new file mode 100644
index 00000000..ded265aa
--- /dev/null
+++ b/python/apt_pkgmodule.cc
@@ -0,0 +1,357 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_pkgmodule.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ apt_pkgmodule - Top level for the python module. Create the internal
+ structures for the module in the interpriter.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_pkgmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/md5.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/pkgsystem.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <python/Python.h>
+ /*}}}*/
+
+// newConfiguration - Build a new configuration class /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_newConfiguration = "Construct a configuration instance";
+static PyObject *newConfiguration(PyObject *self,PyObject *args)
+{
+ return CppPyObject_NEW<Configuration>(&ConfigurationType);
+}
+ /*}}}*/
+
+// Version Wrappers /*{{{*/
+// These are kind of legacy..
+static char *doc_VersionCompare = "VersionCompare(a,b) -> int";
+static PyObject *VersionCompare(PyObject *Self,PyObject *Args)
+{
+ char *A;
+ char *B;
+ int LenA;
+ int LenB;
+
+ if (PyArg_ParseTuple(Args,"s#s#",&A,&LenA,&B,&LenB) == 0)
+ return 0;
+
+ if (_system == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ return Py_BuildValue("i",_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB));
+}
+
+static char *doc_CheckDep = "CheckDep(PkgVer,DepOp,DepVer) -> int";
+static PyObject *CheckDep(PyObject *Self,PyObject *Args)
+{
+ char *A;
+ char *B;
+ char *OpStr;
+ unsigned int Op = 0;
+
+ if (PyArg_ParseTuple(Args,"sss",&A,&OpStr,&B) == 0)
+ return 0;
+ if (*debListParser::ConvertRelation(OpStr,Op) != 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"Bad comparision operation");
+ return 0;
+ }
+
+ if (_system == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ return Py_BuildValue("i",_system->VS->CheckDep(A,Op,B));
+// return Py_BuildValue("i",pkgCheckDep(B,A,Op));
+}
+
+static char *doc_UpstreamVersion = "UpstreamVersion(a) -> string";
+static PyObject *UpstreamVersion(PyObject *Self,PyObject *Args)
+{
+ char *Ver;
+ if (PyArg_ParseTuple(Args,"s",&Ver) == 0)
+ return 0;
+ return CppPyString(_system->VS->UpstreamVersion(Ver));
+}
+
+static char *doc_ParseDepends =
+"ParseDepends(s) -> list of tuples\n"
+"\n"
+"The resulting tuples are (Pkg,Ver,Operation). Each anded dependency is a\n"
+"list of or'd dependencies\n"
+"Source depends are evaluated against the curernt arch and only those that\n"
+"Match are returned.";
+static PyObject *RealParseDepends(PyObject *Self,PyObject *Args,
+ bool ParseArchFlags)
+{
+ string Package;
+ string Version;
+ unsigned int Op;
+
+ const char *Start;
+ const char *Stop;
+ int Len;
+
+ if (PyArg_ParseTuple(Args,"s#",&Start,&Len) == 0)
+ return 0;
+ Stop = Start + Len;
+
+ PyObject *List = PyList_New(0);
+ PyObject *LastRow = 0;
+ while (1)
+ {
+ if (Start == Stop)
+ break;
+
+ Start = debListParser::ParseDepends(Start,Stop,Package,Version,Op,
+ ParseArchFlags);
+ if (Start == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"Problem Parsing Dependency");
+ Py_DECREF(List);
+ return 0;
+ }
+
+ if (LastRow == 0)
+ LastRow = PyList_New(0);
+
+ if (Package.empty() == false)
+ {
+ PyObject *Obj;
+ PyList_Append(LastRow,Obj = Py_BuildValue("sss",Package.c_str(),
+ Version.c_str(),
+ pkgCache::CompTypeDeb(Op)));
+ Py_DECREF(Obj);
+ }
+
+ // Group ORd deps into a single row..
+ if ((Op & pkgCache::Dep::Or) != pkgCache::Dep::Or)
+ {
+ if (PyList_Size(LastRow) != 0)
+ PyList_Append(List,LastRow);
+ Py_DECREF(LastRow);
+ LastRow = 0;
+ }
+ }
+ return List;
+}
+static PyObject *ParseDepends(PyObject *Self,PyObject *Args)
+{
+ return RealParseDepends(Self,Args,false);
+}
+static PyObject *ParseSrcDepends(PyObject *Self,PyObject *Args)
+{
+ return RealParseDepends(Self,Args,true);
+}
+ /*}}}*/
+// md5sum - Compute the md5sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_md5sum = "md5sum(String) -> String or md5sum(File) -> String";
+static PyObject *md5sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ // Digest of a string.
+ if (PyString_Check(Obj) != 0)
+ {
+ MD5Summation Sum;
+ Sum.Add(PyString_AsString(Obj));
+ return CppPyString(Sum.Result().Value());
+ }
+
+ // Digest of a file
+ if (PyFile_Check(Obj) != 0)
+ {
+ MD5Summation Sum;
+ int Fd = fileno(PyFile_AsFile(Obj));
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyExc_SystemError);
+ return 0;
+ }
+
+ return CppPyString(Sum.Result().Value());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// init - 3 init functions /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_Init =
+"init() -> None\n"
+"Legacy. Do InitConfig then parse the command line then do InitSystem\n";
+static PyObject *Init(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitConfig(*_config);
+ pkgInitSystem(*_config,_system);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_InitConfig =
+"initconfig() -> None\n"
+"Load the default configuration and the config file\n";
+static PyObject *InitConfig(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitConfig(*_config);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_InitSystem =
+"initsystem() -> None\n"
+"Construct the underlying system\n";
+static PyObject *InitSystem(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitSystem(*_config,_system);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+ /*}}}*/
+
+// initapt_pkg - Core Module Initialization /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static PyMethodDef methods[] =
+{
+ // Constructors
+ {"newConfiguration",newConfiguration,METH_VARARGS,doc_newConfiguration},
+ {"init",Init,METH_VARARGS,doc_Init},
+ {"InitConfig",InitConfig,METH_VARARGS,doc_InitConfig},
+ {"InitSystem",InitSystem,METH_VARARGS,doc_InitSystem},
+
+ // Tag File
+ {"ParseSection",ParseSection,METH_VARARGS,doc_ParseSection},
+ {"ParseTagFile",ParseTagFile,METH_VARARGS,doc_ParseTagFile},
+ {"RewriteSection",RewriteSection,METH_VARARGS,doc_RewriteSection},
+
+ // Command line
+ {"ReadConfigFile",LoadConfig,METH_VARARGS,doc_LoadConfig},
+ {"ReadConfigFileISC",LoadConfigISC,METH_VARARGS,doc_LoadConfig},
+ {"ParseCommandLine",ParseCommandLine,METH_VARARGS,doc_ParseCommandLine},
+
+ // Versioning
+ {"VersionCompare",VersionCompare,METH_VARARGS,doc_VersionCompare},
+ {"CheckDep",CheckDep,METH_VARARGS,doc_CheckDep},
+ {"UpstreamVersion",UpstreamVersion,METH_VARARGS,doc_UpstreamVersion},
+
+ // Depends
+ {"ParseDepends",ParseDepends,METH_VARARGS,doc_ParseDepends},
+ {"ParseSrcDepends",ParseSrcDepends,METH_VARARGS,doc_ParseDepends},
+
+ // Stuff
+ {"md5sum",md5sum,METH_VARARGS,doc_md5sum},
+
+ // Strings
+ {"QuoteString",StrQuoteString,METH_VARARGS,"QuoteString(String,String) -> String"},
+ {"DeQuoteString",StrDeQuote,METH_VARARGS,"DeQuoteString(String) -> String"},
+ {"SizeToStr",StrSizeToStr,METH_VARARGS,"SizeToStr(int) -> String"},
+ {"TimeToStr",StrTimeToStr,METH_VARARGS,"TimeToStr(int) -> String"},
+ {"URItoFileName",StrURItoFileName,METH_VARARGS,"URItoFileName(String) -> String"},
+ {"Base64Encode",StrBase64Encode,METH_VARARGS,"Base64Encode(String) -> String"},
+ {"StringToBool",StrStringToBool,METH_VARARGS,"StringToBool(String) -> int"},
+ {"TimeRFC1123",StrTimeRFC1123,METH_VARARGS,"TimeRFC1123(int) -> String"},
+ {"StrToTime",StrStrToTime,METH_VARARGS,"StrToTime(String) -> Int"},
+
+ // Cache
+ {"GetCache",TmpGetCache,METH_VARARGS,"GetCache() -> PkgCache"},
+ {"GetPkgRecords",GetPkgRecords,METH_VARARGS,"GetPkgRecords(Cache) -> PkgRecrods"},
+
+ {}
+};
+
+static void AddStr(PyObject *Dict,const char *Itm,const char *Str)
+{
+ PyObject *Obj = PyString_FromString(Str);
+ PyDict_SetItemString(Dict,(char *)Itm,Obj);
+ Py_DECREF(Obj);
+}
+
+static void AddInt(PyObject *Dict,const char *Itm,unsigned long I)
+{
+ PyObject *Obj = Py_BuildValue("i",I);
+ PyDict_SetItemString(Dict,(char *)Itm,Obj);
+ Py_DECREF(Obj);
+}
+
+extern "C" void initapt_pkg()
+{
+ PyObject *Module = Py_InitModule("apt_pkg",methods);
+ PyObject *Dict = PyModule_GetDict(Module);
+
+ // Global variable linked to the global configuration class
+ CppPyObject<Configuration *> *Config = CppPyObject_NEW<Configuration *>(&ConfigurationPtrType);
+ Config->Object = _config;
+ PyDict_SetItemString(Dict,"Config",Config);
+ Py_DECREF(Config);
+
+ // Tag file constants
+ PyObject *Obj;
+ PyDict_SetItemString(Dict,"RewritePackageOrder",
+ Obj = CharCharToList(TFRewritePackageOrder));
+ Py_DECREF(Obj);
+ PyDict_SetItemString(Dict,"RewriteSourceOrder",
+ Obj = CharCharToList(TFRewriteSourceOrder));
+ Py_DECREF(Obj);
+
+ // Version..
+ AddStr(Dict,"Version",pkgVersion);
+ AddStr(Dict,"LibVersion",pkgLibVersion);
+ AddStr(Dict,"CPU",pkgCPU);
+ AddStr(Dict,"OS",pkgOS);
+ AddStr(Dict,"Date",__DATE__);
+ AddStr(Dict,"Time",__TIME__);
+
+ // My constants!!
+ AddInt(Dict,"DepDepends",pkgCache::Dep::Depends);
+ AddInt(Dict,"DepPreDepends",pkgCache::Dep::PreDepends);
+ AddInt(Dict,"DepSuggests",pkgCache::Dep::Suggests);
+ AddInt(Dict,"DepRecommends",pkgCache::Dep::Recommends);
+ AddInt(Dict,"DepConflicts",pkgCache::Dep::Conflicts);
+ AddInt(Dict,"DepReplaces",pkgCache::Dep::Replaces);
+ AddInt(Dict,"DepObsoletes",pkgCache::Dep::Obsoletes);
+
+ AddInt(Dict,"PriImportant",pkgCache::State::Important);
+ AddInt(Dict,"PriRequired",pkgCache::State::Required);
+ AddInt(Dict,"PriStandard",pkgCache::State::Standard);
+ AddInt(Dict,"PriOptional",pkgCache::State::Optional);
+ AddInt(Dict,"PriExtra",pkgCache::State::Extra);
+}
+ /*}}}*/
+
diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h
new file mode 100644
index 00000000..5398bd96
--- /dev/null
+++ b/python/apt_pkgmodule.h
@@ -0,0 +1,65 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_pkgmodule.h,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ Prototypes for the module
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef APT_PKGMODULE_H
+#define APT_PKGMODULE_H
+
+#include <python/Python.h>
+
+// Configuration Stuff
+#define Configuration_Check(op) ((op)->ob_type == &ConfigurationType || \
+ (op)->ob_type == &ConfigurationPtrType || \
+ (op)->ob_type == &ConfigurationSubType)
+extern PyTypeObject ConfigurationType;
+extern PyTypeObject ConfigurationPtrType;
+extern PyTypeObject ConfigurationSubType;
+extern PyTypeObject VersionType;
+
+extern char *doc_LoadConfig;
+extern char *doc_LoadConfigISC;
+extern char *doc_ParseCommandLine;
+PyObject *LoadConfig(PyObject *Self,PyObject *Args);
+PyObject *LoadConfigISC(PyObject *Self,PyObject *Args);
+PyObject *ParseCommandLine(PyObject *Self,PyObject *Args);
+
+// Tag File Stuff
+extern PyTypeObject TagSecType;
+extern PyTypeObject TagFileType;
+extern char *doc_ParseSection;
+extern char *doc_ParseTagFile;
+extern char *doc_RewriteSection;
+PyObject *ParseSection(PyObject *self,PyObject *Args);
+PyObject *ParseTagFile(PyObject *self,PyObject *Args);
+PyObject *RewriteSection(PyObject *self,PyObject *Args);
+
+// String Stuff
+PyObject *StrQuoteString(PyObject *self,PyObject *Args);
+PyObject *StrDeQuote(PyObject *self,PyObject *Args);
+PyObject *StrSizeToStr(PyObject *self,PyObject *Args);
+PyObject *StrTimeToStr(PyObject *self,PyObject *Args);
+PyObject *StrURItoFileName(PyObject *self,PyObject *Args);
+PyObject *StrBase64Encode(PyObject *self,PyObject *Args);
+PyObject *StrStringToBool(PyObject *self,PyObject *Args);
+PyObject *StrTimeRFC1123(PyObject *self,PyObject *Args);
+PyObject *StrStrToTime(PyObject *self,PyObject *Args);
+
+// Cache Stuff
+extern PyTypeObject PkgCacheType;
+extern PyTypeObject PkgListType;
+extern PyTypeObject PackageType;
+extern PyTypeObject PackageFileType;
+extern PyTypeObject DependencyType;
+extern PyTypeObject RDepListType;
+PyObject *TmpGetCache(PyObject *Self,PyObject *Args);
+
+// PkgRecords Stuff
+extern PyTypeObject PkgRecordsType;
+PyObject *GetPkgRecords(PyObject *Self,PyObject *Args);
+
+#endif
diff --git a/python/cache.cc b/python/cache.cc
new file mode 100644
index 00000000..794b4f57
--- /dev/null
+++ b/python/cache.cc
@@ -0,0 +1,731 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: cache.cc,v 1.1 2001/02/20 06:32:01 jgg 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/sptr.h>
+
+#include <python/Python.h>
+ /*}}}*/
+
+struct PkgListStruct
+{
+ pkgCache::PkgIterator Iter;
+ unsigned long LastIndex;
+
+ PkgListStruct(pkgCache::PkgIterator const &I) : Iter(I), LastIndex(0) {}
+ PkgListStruct() {abort();}; // G++ Bug..
+};
+
+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 = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType,
+ I.OwnerVer());
+ Obj = Py_BuildValue("ssN",I.ParentPkg().Name(),I.ProvideVersion(),
+ Ver);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+// Cache Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *CacheAttr(PyObject *Self,char *Name)
+{
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+
+ if (strcmp("Packages",Name) == 0)
+ return CppOwnedPyObject_NEW<PkgListStruct>(Self,&PkgListType,Cache->PkgBegin());
+ else if (strcmp("PackageCount",Name) == 0)
+ return Py_BuildValue("i",Cache->HeaderP->PackageCount);
+ else if (strcmp("VersionCount",Name) == 0)
+ return Py_BuildValue("i",Cache->HeaderP->VersionCount);
+ else if (strcmp("DependsCount",Name) == 0)
+ return Py_BuildValue("i",Cache->HeaderP->DependsCount);
+ else if (strcmp("PackageFileCount",Name) == 0)
+ return Py_BuildValue("i",Cache->HeaderP->PackageFileCount);
+ else if (strcmp("VerFileCount",Name) == 0)
+ return Py_BuildValue("i",Cache->HeaderP->VerFileCount);
+ else if (strcmp("ProvidesCount",Name) == 0)
+ return Py_BuildValue("i",Cache->HeaderP->ProvidesCount);
+ else if (strcmp("FileList",Name) == 0)
+ {
+ PyObject *List = PyList_New(0);
+ for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I.end() == false; I++)
+ {
+ PyObject *Obj;
+ Obj = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Self,&PackageFileType,I);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+ }
+
+ PyErr_SetString(PyExc_AttributeError,Name);
+ return 0;
+}
+
+// Map access, operator []
+static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg)
+{
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+
+ if (PyString_Check(Arg) == 0)
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return 0;
+ }
+
+ // Search for the package
+ const char *Name = PyString_AsString(Arg);
+ pkgCache::PkgIterator Pkg = Cache->FindPkg(Name);
+ if (Pkg.end() == true)
+ {
+ PyErr_SetString(PyExc_KeyError,Name);
+ return 0;
+ }
+
+ return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Self,&PackageType,Pkg);
+}
+
+static PyMappingMethods CacheMap = {0,CacheMapOp,0};
+PyTypeObject PkgCacheType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgCache", // tp_name
+ sizeof(CppOwnedPyObject<pkgCache *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<pkgCache *>, // tp_dealloc
+ 0, // tp_print
+ CacheAttr, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ &CacheMap, // tp_as_mapping
+ 0, // tp_hash
+};
+
+ /*}}}*/
+// Package List Class /*{{{*/
+// ---------------------------------------------------------------------
+static int PkgListLen(PyObject *Self)
+{
+ return GetCpp<PkgListStruct>(Self).Iter.Cache()->HeaderP->PackageCount;
+}
+
+static PyObject *PkgListItem(PyObject *iSelf,int Index)
+{
+ PkgListStruct &Self = GetCpp<PkgListStruct>(iSelf);
+ if (Index < 0 || (unsigned)Index >= Self.Iter.Cache()->HeaderP->PackageCount)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+
+ if ((unsigned)Index < Self.LastIndex)
+ {
+ Self.LastIndex = 0;
+ Self.Iter = Self.Iter.Cache()->PkgBegin();
+ }
+
+ while ((unsigned)Index > Self.LastIndex)
+ {
+ Self.LastIndex++;
+ Self.Iter++;
+ if (Self.Iter.end() == true)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+ }
+
+ return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PackageType,
+ Self.Iter);
+}
+
+static PySequenceMethods PkgListSeq =
+{
+ PkgListLen,
+ 0, // concat
+ 0, // repeat
+ PkgListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+PyTypeObject PkgListType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgCache::PkgIterator", // tp_name
+ sizeof(CppOwnedPyObject<PkgListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<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
+};
+
+ /*}}}*/
+// Package Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *PackageAttr(PyObject *Self,char *Name)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self);
+
+ if (strcmp("Name",Name) == 0)
+ return PyString_FromString(Pkg.Name());
+ else if (strcmp("VersionList",Name) == 0)
+ {
+ PyObject *List = PyList_New(0);
+ for (pkgCache::VerIterator I = Pkg.VersionList(); I.end() == false; I++)
+ {
+ PyObject *Obj;
+ Obj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType,I);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+ }
+ else if (strcmp("CurrentVer",Name) == 0)
+ {
+ if (Pkg->CurrentVer == 0)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType,
+ Pkg.CurrentVer());
+ }
+ else if (strcmp("Section",Name) == 0)
+ return Safe_FromString(Pkg.Section());
+ else if (strcmp("RevDependsList",Name) == 0)
+ return CppOwnedPyObject_NEW<RDepListStruct>(Owner,&RDepListType,
+ Pkg.RevDependsList());
+ else if (strcmp("ProvidesList",Name) == 0)
+ return CreateProvides(Owner,Pkg.ProvidesList());
+ else if (strcmp("SelectedState",Name) == 0)
+ return Py_BuildValue("i",Pkg->SelectedState);
+ else if (strcmp("InstState",Name) == 0)
+ return Py_BuildValue("i",Pkg->InstState);
+ else if (strcmp("CurrentState",Name) == 0)
+ return Py_BuildValue("i",Pkg->CurrentState);
+ else if (strcmp("ID",Name) == 0)
+ return Py_BuildValue("i",Pkg->ID);
+ else if (strcmp("Auto",Name) == 0)
+ return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Auto) != 0);
+ else if (strcmp("Essential",Name) == 0)
+ return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Essential) != 0);
+ else if (strcmp("Important",Name) == 0)
+ return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Important) != 0);
+
+ PyErr_SetString(PyExc_AttributeError,Name);
+ return 0;
+}
+
+static PyObject *PackageRepr(PyObject *Self)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+
+ char S[300];
+ snprintf(S,sizeof(S),"<pkgCache::Package object: Name:'%s' Section: '%s'"
+ " ID:%u Flags:0x%lX>",
+ Pkg.Name(),Pkg.Section(),Pkg->ID,Pkg->Flags);
+ return PyString_FromString(S);
+}
+
+PyTypeObject PackageType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgCache::Package", // tp_name
+ sizeof(CppOwnedPyObject<pkgCache::PkgIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<pkgCache::PkgIterator>, // tp_dealloc
+ 0, // tp_print
+ PackageAttr, // 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
+};
+ /*}}}*/
+// 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; D++)
+ {
+ pkgCache::DepIterator Start;
+ pkgCache::DepIterator End;
+ D.GlobOr(Start,End);
+
+ // Switch/create a new dict entry
+ if (LastDepType != Start->Type || LastDep != 0)
+ {
+ PyObject *Dep = PyString_FromString(Start.DepType());
+ 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 = CppOwnedPyObject_NEW<pkgCache::DepIterator>(Owner,&DependencyType,
+ 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 PyObject *VersionAttr(PyObject *Self,char *Name)
+{
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+
+ if (strcmp("VerStr",Name) == 0)
+ return PyString_FromString(Ver.VerStr());
+ else if (strcmp("Section",Name) == 0)
+ return Safe_FromString(Ver.Section());
+ else if (strcmp("Arch",Name) == 0)
+ return Safe_FromString(Ver.Arch());
+ else if (strcmp("FileList",Name) == 0)
+ {
+ /* 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::VerFileIterator I = Ver.FileList(); I.end() == false; I++)
+ {
+ PyObject *PkgFile;
+ PyObject *Obj;
+ PkgFile = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PackageFileType,I.File());
+ Obj = Py_BuildValue("Nl",PkgFile,I.Index());
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+ }
+ else if (strcmp("DependsListStr",Name) == 0)
+ return MakeDepends(Owner,Ver,false);
+ else if (strcmp("DependsList",Name) == 0)
+ return MakeDepends(Owner,Ver,true);
+ else if (strcmp("ParentPkg",Name) == 0)
+ return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType,
+ Ver.ParentPkg());
+ else if (strcmp("ProvidesList",Name) == 0)
+ return CreateProvides(Owner,Ver.ProvidesList());
+ else if (strcmp("Size",Name) == 0)
+ return Py_BuildValue("i",Ver->Size);
+ else if (strcmp("InstalledSize",Name) == 0)
+ return Py_BuildValue("i",Ver->InstalledSize);
+ else if (strcmp("Hash",Name) == 0)
+ return Py_BuildValue("i",Ver->Hash);
+ else if (strcmp("ID",Name) == 0)
+ return Py_BuildValue("i",Ver->ID);
+ else if (strcmp("Priority",Name) == 0)
+ return Py_BuildValue("i",Ver->Priority);
+ else if (strcmp("PriorityStr",Name) == 0)
+ return PyString_FromString(Ver.PriorityType());
+
+ PyErr_SetString(PyExc_AttributeError,Name);
+ return 0;
+}
+
+static PyObject *VersionRepr(PyObject *Self)
+{
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+
+ char S[300];
+ snprintf(S,sizeof(S),"<pkgCache::Version object: Pkg:'%s' Ver:'%s' "
+ "Section:'%s' Arch:'%s' Size:%lu ISize:%lu Hash:%u "
+ "ID:%u Priority:%u>",
+ 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);
+}
+
+PyTypeObject VersionType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgCache::VerIterator", // tp_name
+ sizeof(CppOwnedPyObject<pkgCache::VerIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<pkgCache::VerIterator>, // tp_dealloc
+ 0, // tp_print
+ VersionAttr, // 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
+};
+
+ /*}}}*/
+// PackageFile Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *PackageFileAttr(PyObject *Self,char *Name)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+// PyObject *Owner = GetOwner<pkgCache::PkgFileIterator>(Self);
+
+ if (strcmp("FileName",Name) == 0)
+ return Safe_FromString(File.FileName());
+ else if (strcmp("Archive",Name) == 0)
+ return Safe_FromString(File.Archive());
+ else if (strcmp("Component",Name) == 0)
+ return Safe_FromString(File.Component());
+ else if (strcmp("Version",Name) == 0)
+ return Safe_FromString(File.Version());
+ else if (strcmp("Origin",Name) == 0)
+ return Safe_FromString(File.Origin());
+ else if (strcmp("Label",Name) == 0)
+ return Safe_FromString(File.Label());
+ else if (strcmp("Architecture",Name) == 0)
+ return Safe_FromString(File.Architecture());
+ else if (strcmp("Site",Name) == 0)
+ return Safe_FromString(File.Site());
+ else if (strcmp("IndexType",Name) == 0)
+ return Safe_FromString(File.IndexType());
+ else if (strcmp("Size",Name) == 0)
+ return Py_BuildValue("i",File->Size);
+ else if (strcmp("NotSource",Name) == 0)
+ return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotSource) != 0);
+ else if (strcmp("NotAutomatic",Name) == 0)
+ return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotAutomatic) != 0);
+ else if (strcmp("ID",Name) == 0)
+ return Py_BuildValue("i",File->ID);
+ /* mtime is really a cookie these days and has no meaning outside the
+ list handlers */
+
+ PyErr_SetString(PyExc_AttributeError,Name);
+ return 0;
+}
+
+static PyObject *PackageFileRepr(PyObject *Self)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+
+ char S[300];
+ snprintf(S,sizeof(S),"<pkgCache::PackageFile object: "
+ "File:'%s' a=%s,c=%s,v=%s,o=%s,l=%s "
+ "Arch='%s' Site='%s' IndexType='%s' Size=%lu "
+ "Flags=0x%lX ID:%u>",
+ 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);
+}
+
+PyTypeObject PackageFileType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgCache::PkgFileIterator", // tp_name
+ sizeof(CppOwnedPyObject<pkgCache::PkgFileIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<pkgCache::PkgFileIterator>, // tp_dealloc
+ 0, // tp_print
+ PackageFileAttr, // 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
+};
+
+ /*}}}*/
+// Dependency Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyMethodDef DependencyMethods[];
+
+static PyObject *DependencyAttr(PyObject *Self,char *Name)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+
+ if (strcmp("TargetVer",Name) == 0)
+ {
+ if (Dep->Version == 0)
+ return PyString_FromString("");
+ return PyString_FromString(Dep.TargetVer());
+ }
+ else if (strcmp("TargetPkg",Name) == 0)
+ return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType,
+ Dep.TargetPkg());
+ else if (strcmp("ParentVer",Name) == 0)
+ return CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType,
+ Dep.ParentVer());
+ else if (strcmp("ParentPkg",Name) == 0)
+ return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType, Dep.ParentPkg());
+ else if (strcmp("CompType",Name) == 0)
+ return PyString_FromString(Dep.CompType());
+ else if (strcmp("DepType",Name) == 0)
+ return PyString_FromString(Dep.DepType());
+ else if (strcmp("ID",Name) == 0)
+ return Py_BuildValue("i",Dep->ID);
+
+ return Py_FindMethod(DependencyMethods,Self,Name);
+}
+
+static PyObject *DependencyRepr(PyObject *Self)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+
+ char S[300];
+ snprintf(S,sizeof(S),"<pkgCache::Dependency object: "
+ "Pkg:'%s' Ver:'%s' Comp:'%s'>",
+ Dep.TargetPkg().Name(),
+ (Dep.TargetVer() == 0?"":Dep.TargetVer()),
+ Dep.CompType());
+ return PyString_FromString(S);
+}
+
+static PyObject *DepSmartTargetPkg(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+
+ pkgCache::PkgIterator P;
+ if (Dep.SmartTargetPkg(P) == false)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType,P);
+}
+
+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);
+
+ SPtr<pkgCache::Version *> Vers = Dep.AllTargets();
+ PyObject *List = PyList_New(0);
+ for (pkgCache::Version **I = Vers; *I != 0; I++)
+ {
+ PyObject *Obj;
+ Obj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType,
+ pkgCache::VerIterator(*Dep.Cache(),*I));
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyMethodDef DependencyMethods[] =
+{
+ {"SmartTargetPkg",DepSmartTargetPkg,METH_VARARGS,"Returns the natural Target or None"},
+ {"AllTargets",DepAllTargets,METH_VARARGS,"Returns all possible Versions that match this dependency"},
+ {}
+};
+
+PyTypeObject DependencyType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgCache::DepIterator", // tp_name
+ sizeof(CppOwnedPyObject<pkgCache::DepIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<pkgCache::DepIterator>, // tp_dealloc
+ 0, // tp_print
+ DependencyAttr, // 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
+};
+
+ /*}}}*/
+// Reverse Dependency List Class /*{{{*/
+// ---------------------------------------------------------------------
+static int RDepListLen(PyObject *Self)
+{
+ return GetCpp<RDepListStruct>(Self).Len;
+}
+
+static PyObject *RDepListItem(PyObject *iSelf,int 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 CppOwnedPyObject_NEW<pkgCache::DepIterator>(GetOwner<RDepListStruct>(iSelf),
+ &DependencyType,Self.Iter);
+}
+
+static PySequenceMethods RDepListSeq =
+{
+ RDepListLen,
+ 0, // concat
+ 0, // repeat
+ RDepListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+PyTypeObject RDepListType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgCache::DepIterator", // tp_name
+ sizeof(CppOwnedPyObject<RDepListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<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
+};
+
+ /*}}}*/
+
+PyObject *TmpGetCache(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgCacheFile *Cache = new pkgCacheFile();
+ OpTextProgress Prog;
+ if (Cache->Open(Prog,false) == false)
+ return HandleErrors();
+
+ return CppOwnedPyObject_NEW<pkgCache *>(0,&PkgCacheType,(pkgCache *)(*Cache));
+}
diff --git a/python/configuration.cc b/python/configuration.cc
new file mode 100644
index 00000000..9667f190
--- /dev/null
+++ b/python/configuration.cc
@@ -0,0 +1,523 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: configuration.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ Configuration - Binding for the configuration object.
+
+ There are three seperate classes..
+ Configuration - A stand alone configuration instance
+ ConfigurationPtr - A pointer to a configuration instance, used only
+ for the global instance (_config)
+ ConfigurationSub - A subtree - has a reference to its owner.
+
+ The wrapping is mostly 1:1 with the C++ code, but there are additions to
+ wrap the linked tree walking into nice flat sequence walking.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/cmndline.h>
+
+#include <python/Python.h>
+ /*}}}*/
+static PyMethodDef CnfMethods[];
+
+/* If we create a sub tree then it is of this type, the Owner is used
+ to manage reference counting. */
+struct SubConfiguration : public CppPyObject<Configuration>
+{
+ PyObject *Owner;
+};
+
+// CnfGetAttr - Get an attribute - variable/method /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static PyObject *CnfGetAttr(PyObject *Self,char *Name)
+{
+ return Py_FindMethod(CnfMethods,Self,Name);
+}
+ /*}}}*/
+// CnfSubFree - Free a sub configuration /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void CnfSubFree(PyObject *Obj)
+{
+ SubConfiguration *Self = (SubConfiguration *)Obj;
+ Py_DECREF(Self->Owner);
+ CppDealloc<Configuration>(Obj);
+}
+ /*}}}*/
+
+// GetSelf - Convert PyObject to Configuration /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static inline Configuration &GetSelf(PyObject *Obj)
+{
+ if (Obj->ob_type == &ConfigurationPtrType)
+ return *GetCpp<Configuration *>(Obj);
+ return GetCpp<Configuration>(Obj);
+}
+ /*}}}*/
+
+// Method Wrappers /*{{{*/
+static char *doc_Find = "Find(Name[,default]) -> String/None";
+static PyObject *CnfFind(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyString(GetSelf(Self).Find(Name,Default));
+}
+
+static char *doc_FindFile = "FindFile(Name[,default]) -> String/None";
+static PyObject *CnfFindFile(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyString(GetSelf(Self).FindFile(Name,Default));
+}
+
+static char *doc_FindDir = "FindDir(Name[,default]) -> String/None";
+static PyObject *CnfFindDir(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyString(GetSelf(Self).FindDir(Name,Default));
+}
+
+static char *doc_FindI = "FindI(Name[,default]) -> Integer";
+static PyObject *CnfFindI(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ int Default = 0;
+ if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0)
+ return 0;
+ return Py_BuildValue("i",GetSelf(Self).FindI(Name,Default));
+}
+
+static char *doc_FindB = "FindB(Name[,default]) -> Integer";
+static PyObject *CnfFindB(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ int Default = 0;
+ if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0)
+ return 0;
+ return Py_BuildValue("i",(int)GetSelf(Self).FindB(Name,(Default == 0?false:true)));
+}
+
+static char *doc_Set = "Set(Name,Value) -> None";
+static PyObject *CnfSet(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Value = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Name,&Value) == 0)
+ return 0;
+
+ GetSelf(Self).Set(Name,Value);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char *doc_Exists = "Exists(Name) -> Integer";
+static PyObject *CnfExists(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+ return Py_BuildValue("i",(int)GetSelf(Self).Exists(Name));
+}
+
+static char *doc_Clear = "Clear(Name) -> None";
+static PyObject *CnfClear(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ GetSelf(Self).Clear(Name);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+// The amazing narrowing search ability!
+static char *doc_SubTree = "SubTree(Name) -> Configuration";
+static PyObject *CnfSubTree(PyObject *Self,PyObject *Args)
+{
+ char *Name;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+ const Configuration::Item *Itm = GetSelf(Self).Tree(Name);
+ if (Itm == 0)
+ {
+ PyErr_SetString(PyExc_KeyError,Name);
+ return 0;
+ }
+
+ // Create a new sub configuration.
+ SubConfiguration *New = PyObject_NEW(SubConfiguration,&ConfigurationSubType);
+ new (&New->Object) Configuration(Itm);
+ New->Owner = Self;
+ Py_INCREF(Self);
+ return New;
+}
+
+// Return a list of items at a specific level
+static char *doc_List = "List([root]) -> List";
+static PyObject *CnfList(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ const Configuration::Item *Root = GetSelf(Self).Tree(0)->Parent;
+ if (Top != 0 && RootName != 0)
+ Top = Top->Child;
+ for (; Top != 0; Top = Top->Next)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->FullTag(Root)));
+ Py_DECREF(Obj);
+ }
+
+ return List;
+}
+
+/* Return a list of values of items at a specific level.. This is used to
+ get out value lists */
+static char *doc_ValueList = "ValueList([root]) -> List";
+static PyObject *CnfValueList(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ if (Top != 0 && RootName != 0)
+ Top = Top->Child;
+ for (; Top != 0; Top = Top->Next)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->Value));
+ Py_DECREF(Obj);
+ }
+
+ return List;
+}
+
+static char *doc_MyTag = "MyTag() -> String";
+static PyObject *CnfMyTag(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ const Configuration::Item *Top = GetSelf(Self).Tree(0);
+ if (Top == 0)
+ return Py_BuildValue("s","");
+ return CppPyString(Top->Parent->Tag);
+}
+
+// Look like a mapping
+static char *doc_Keys = "keys([root]) -> List";
+static PyObject *CnfKeys(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ const Configuration::Item *Stop = Top;
+ if (RootName == 0)
+ Stop = 0;
+ const Configuration::Item *Root = GetSelf(Self).Tree(0)->Parent;
+ for (; Top != 0;)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->FullTag(Root)));
+ Py_DECREF(Obj);
+
+ if (Top->Child != 0)
+ {
+ Top = Top->Child;
+ continue;
+ }
+
+ while (Top != 0 && Top->Next == 0 && Top != Root &&
+ Top->Parent != Stop)
+ Top = Top->Parent;
+ if (Top != 0)
+ Top = Top->Next;
+ }
+
+ return List;
+}
+
+// Map access, operator []
+static PyObject *CnfMap(PyObject *Self,PyObject *Arg)
+{
+ if (PyString_Check(Arg) == 0)
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return 0;
+ }
+
+ if (GetSelf(Self).Exists(PyString_AsString(Arg)) == false)
+ {
+ PyErr_SetString(PyExc_KeyError,PyString_AsString(Arg));
+ return 0;
+ }
+
+ return CppPyString(GetSelf(Self).Find(PyString_AsString(Arg)));
+}
+
+// Assignment with operator []
+static int CnfMapSet(PyObject *Self,PyObject *Arg,PyObject *Val)
+{
+ if (PyString_Check(Arg) == 0 || PyString_Check(Val) == 0)
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return -1;
+ }
+
+ GetSelf(Self).Set(PyString_AsString(Arg),PyString_AsString(Val));
+ return 0;
+}
+ /*}}}*/
+// Config file loaders /*{{{*/
+char *doc_LoadConfig = "LoadConfig(Configuration,FileName) -> None";
+PyObject *LoadConfig(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"Os",&Self,&Name) == 0)
+ return 0;
+ if (Configuration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigFile(GetSelf(Self),Name,false) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+char *doc_LoadConfigISC = "LoadConfigISC(Configuration,FileName) -> None";
+PyObject *LoadConfigISC(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"Os",&Self,&Name) == 0)
+ return 0;
+ if (Configuration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigFile(GetSelf(Self),Name,true) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+ /*}}}*/
+
+// ParseCommandLine - Wrapper for the command line interface /*{{{*/
+// ---------------------------------------------------------------------
+char *doc_ParseCommandLine =
+"ParseCommandLine(Configuration,ListOfOptions,List-argv) -> List\n"
+"\n"
+"This function is like getopt except it manipulates a configuration space.\n"
+"output is a list of non-option arguments (filenames, etc).\n"
+"ListOfOptions is a list of tuples of the form:\n"
+" ('c',\"long-opt or None\",\"Configuration::Variable\",\"optional type\")\n"
+"Where type may be one of HasArg, IntLevel, Boolean, InvBoolean,\n"
+"ConfigFile, or ArbItem. The default is Boolean.";
+PyObject *ParseCommandLine(PyObject *Self,PyObject *Args)
+{
+ PyObject *POList;
+ PyObject *Pargv;
+ if (PyArg_ParseTuple(Args,"OO!O!",&Self,
+ &PyList_Type,&POList,&PyList_Type,&Pargv) == 0)
+ return 0;
+ if (Configuration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ // Convert the option list
+ int Length = PySequence_Length(POList);
+ CommandLine::Args *OList = new CommandLine::Args[Length+1];
+ OList[Length].ShortOpt = 0;
+ OList[Length].LongOpt = 0;
+
+ for (int I = 0; I != Length; I++)
+ {
+ char *Type = 0;
+ if (PyArg_ParseTuple(PySequence_GetItem(POList,I),"czs|s",
+ &OList[I].ShortOpt,&OList[I].LongOpt,
+ &OList[I].ConfName,&Type) == 0)
+ {
+ delete [] OList;
+ return 0;
+ }
+ OList[I].Flags = 0;
+
+ // Convert the type over to flags..
+ if (Type != 0)
+ {
+ if (strcasecmp(Type,"HasArg") == 0)
+ OList[I].Flags = CommandLine::HasArg;
+ else if (strcasecmp(Type,"IntLevel") == 0)
+ OList[I].Flags = CommandLine::IntLevel;
+ else if (strcasecmp(Type,"Boolean") == 0)
+ OList[I].Flags = CommandLine::Boolean;
+ else if (strcasecmp(Type,"InvBoolean") == 0)
+ OList[I].Flags = CommandLine::InvBoolean;
+ else if (strcasecmp(Type,"ConfigFile") == 0)
+ OList[I].Flags = CommandLine::ConfigFile;
+ else if (strcasecmp(Type,"ArbItem") == 0)
+ OList[I].Flags = CommandLine::ArbItem;
+ }
+ }
+
+ // Convert the argument list into a char **
+ const char **argv = ListToCharChar(Pargv);
+ if (argv == 0)
+ {
+ delete [] OList;
+ return 0;
+ }
+
+ // Do the command line processing
+ PyObject *List = 0;
+ {
+ CommandLine CmdL(OList,&GetSelf(Self));
+ if (CmdL.Parse(PySequence_Length(Pargv),argv) == false)
+ {
+ delete [] argv;
+ delete [] OList;
+ return HandleErrors();
+ }
+
+ // Convert the file listing into a python sequence
+ for (Length = 0; CmdL.FileList[Length] != 0; Length++);
+ List = PyList_New(Length);
+ for (int I = 0; CmdL.FileList[I] != 0; I++)
+ {
+ PyList_SetItem(List,I,PyString_FromString(CmdL.FileList[I]));
+ }
+ }
+
+ delete [] argv;
+ delete [] OList;
+ return HandleErrors(List);
+}
+ /*}}}*/
+
+// Method table for the Configuration object
+static PyMethodDef CnfMethods[] =
+{
+ // Query
+ {"Find",CnfFind,METH_VARARGS,doc_Find},
+ {"FindFile",CnfFindFile,METH_VARARGS,doc_FindFile},
+ {"FindDir",CnfFindDir,METH_VARARGS,doc_FindDir},
+ {"FindI",CnfFindI,METH_VARARGS,doc_FindI},
+ {"FindB",CnfFindB,METH_VARARGS,doc_FindB},
+
+ // Others
+ {"Set",CnfSet,METH_VARARGS,doc_Set},
+ {"Exists",CnfExists,METH_VARARGS,doc_Exists},
+ {"SubTree",CnfSubTree,METH_VARARGS,doc_SubTree},
+ {"List",CnfList,METH_VARARGS,doc_List},
+ {"ValueList",CnfValueList,METH_VARARGS,doc_ValueList},
+ {"MyTag",CnfMyTag,METH_VARARGS,doc_MyTag},
+ {"Clear",CnfClear,METH_VARARGS,doc_Clear},
+
+ // Python Special
+ {"keys",CnfKeys,METH_VARARGS,doc_Keys},
+ {"has_key",CnfExists,METH_VARARGS,doc_Exists},
+ {"get",CnfFind,METH_VARARGS,doc_Find},
+ {}
+};
+
+// Type for a Normal Configuration object
+static PyMappingMethods ConfigurationMap = {0,CnfMap,CnfMapSet};
+PyTypeObject ConfigurationType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "Configuration", // tp_name
+ sizeof(CppPyObject<Configuration>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<Configuration>, // tp_dealloc
+ 0, // tp_print
+ CnfGetAttr, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ &ConfigurationMap, // tp_as_mapping
+ 0, // tp_hash
+};
+
+PyTypeObject ConfigurationPtrType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "ConfigurationPtr", // tp_name
+ sizeof(CppPyObject<Configuration *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ (destructor)PyMem_Free, // tp_dealloc
+ 0, // tp_print
+ CnfGetAttr, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ &ConfigurationMap, // tp_as_mapping
+ 0, // tp_hash
+};
+
+PyTypeObject ConfigurationSubType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "ConfigurationSub", // tp_name
+ sizeof(SubConfiguration), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CnfSubFree, // tp_dealloc
+ 0, // tp_print
+ CnfGetAttr, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ &ConfigurationMap, // tp_as_mapping
+ 0, // tp_hash
+};
+
diff --git a/python/generic.cc b/python/generic.cc
new file mode 100644
index 00000000..aab03d7b
--- /dev/null
+++ b/python/generic.cc
@@ -0,0 +1,86 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: generic.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ generic - Some handy functions to make integration a tad simpler
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+
+#include <apt-pkg/error.h>
+ /*}}}*/
+
+// HandleErrors - This moves errors from _error to Python Exceptions /*{{{*/
+// ---------------------------------------------------------------------
+/* We throw away all warnings and only propogate the first error. */
+PyObject *HandleErrors(PyObject *Res)
+{
+ if (_error->PendingError() == false)
+ {
+ // Throw away warnings
+ _error->Discard();
+ return Res;
+ }
+
+ if (Res != 0)
+ Py_DECREF(Res);
+
+ string Err = "Internal Error Error";
+ while (_error->empty() == false)
+ {
+ bool Type = _error->PopMessage(Err);
+ if (Type == false)
+ continue;
+ }
+
+ _error->Discard();
+ PyErr_SetString(PyExc_SystemError,Err.c_str());
+ return 0;
+}
+ /*}}}*/
+// ListToCharChar - Convert a list to an array of char char /*{{{*/
+// ---------------------------------------------------------------------
+/* Caller must free the result. 0 on error. */
+const char **ListToCharChar(PyObject *List,bool NullTerm)
+{
+ // Convert the argument list into a char **
+ int Length = PySequence_Length(List);
+ const char **Res = new const char *[Length + (NullTerm == true?1:0)];
+ for (int I = 0; I != Length; I++)
+ {
+ PyObject *Itm = PySequence_GetItem(List,I);
+ if (PyString_Check(Itm) == 0)
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ delete [] Res;
+ return 0;
+ }
+ Res[I] = PyString_AsString(Itm);
+ }
+ if (NullTerm == true)
+ Res[Length] = 0;
+ return Res;
+}
+ /*}}}*/
+// CharCharToList - Inverse of the above /*{{{*/
+// ---------------------------------------------------------------------
+/* Zero size indicates the list is Null terminated. */
+PyObject *CharCharToList(const char **List,unsigned long Size)
+{
+ if (Size == 0)
+ {
+ for (const char **I = List; *I != 0; I++)
+ Size++;
+ }
+
+ // Convert the whole configuration space into a list
+ PyObject *PList = PyList_New(Size);
+ for (unsigned long I = 0; I != Size; I++, List++)
+ PyList_SetItem(PList,I,PyString_FromString(*List));
+
+ return PList;
+}
+ /*}}}*/
diff --git a/python/generic.h b/python/generic.h
new file mode 100644
index 00000000..3cbe374b
--- /dev/null
+++ b/python/generic.h
@@ -0,0 +1,132 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: generic.h,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ generic - Some handy functions to make integration a tad simpler
+
+ Python needs this little _HEAD tacked onto the front of the object..
+ This complicates the integration with C++. We use some templates to
+ make that quite transparent to us. It would have been nice if Python
+ internally used a page from the C++ ref counting book to hide its little
+ header from the world, but it doesn't.
+
+ The CppPyObject has the target object and the Python header, this is
+ needed to ensure proper alignment.
+ GetCpp returns the C++ object from a PyObject.
+ CppPyObject_NEW creates the Python object and then uses placement new
+ to init the C++ class.. This is good for simple situations and as an
+ example on how to do it in other more specific cases.
+ CppPyObject_Dealloc should be used in the Type as the destructor
+ function.
+ HandleErrors converts errors from the internal _error stack into Python
+ exceptions and makes sure the _error stack is empty.
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef GENERIC_H
+#define GENERIC_H
+
+#include <python/Python.h>
+#include <string>
+
+template <class T> struct CppPyObject : public PyObject
+{
+ T Object;
+};
+
+template <class T> struct CppOwnedPyObject : public CppPyObject<T>
+{
+ PyObject *Owner;
+};
+
+template <class T>
+inline T &GetCpp(PyObject *Obj)
+{
+ return ((CppPyObject<T> *)Obj)->Object;
+}
+
+template <class T>
+inline PyObject *GetOwner(PyObject *Obj)
+{
+ return ((CppOwnedPyObject<T> *)Obj)->Owner;
+}
+
+// Generic 'new' functions
+template <class T>
+inline CppPyObject<T> *CppPyObject_NEW(PyTypeObject *Type)
+{
+ CppPyObject<T> *New = PyObject_NEW(CppPyObject<T>,Type);
+ new (&New->Object) T;
+ return New;
+}
+
+template <class T,class A>
+inline CppPyObject<T> *CppPyObject_NEW(PyTypeObject *Type,A const &Arg)
+{
+ CppPyObject<T> *New = PyObject_NEW(CppPyObject<T>,Type);
+ new (&New->Object) T(Arg);
+ return New;
+}
+
+template <class T>
+inline CppOwnedPyObject<T> *CppOwnedPyObject_NEW(PyObject *Owner,
+ PyTypeObject *Type)
+{
+ CppOwnedPyObject<T> *New = PyObject_NEW(CppOwnedPyObject<T>,Type);
+ new (&New->Object) T;
+ New->Owner = Owner;
+ Py_INCREF(Owner);
+ return New;
+}
+
+template <class T,class A>
+inline CppOwnedPyObject<T> *CppOwnedPyObject_NEW(PyObject *Owner,
+ PyTypeObject *Type,A const &Arg)
+{
+ CppOwnedPyObject<T> *New = PyObject_NEW(CppOwnedPyObject<T>,Type);
+ new (&New->Object) T(Arg);
+ New->Owner = Owner;
+ if (Owner != 0)
+ Py_INCREF(Owner);
+ return New;
+}
+
+// Generic Dealloc type functions
+template <class T>
+void CppDealloc(PyObject *Obj)
+{
+ GetCpp<T>(Obj).~T();
+ PyMem_DEL(Obj);
+}
+
+template <class T>
+void CppOwnedDealloc(PyObject *iObj)
+{
+ CppOwnedPyObject<T> *Obj = (CppOwnedPyObject<T> *)iObj;
+ Obj->Object.~T();
+ if (Obj->Owner != 0)
+ Py_DECREF(Obj->Owner);
+ PyMem_DEL(Obj);
+}
+
+inline PyObject *CppPyString(string Str)
+{
+ return PyString_FromStringAndSize(Str.begin(),Str.length());
+}
+
+inline PyObject *Safe_FromString(const char *Str)
+{
+ if (Str == 0)
+ return PyString_FromString("");
+ return PyString_FromString(Str);
+}
+
+// Convert _error into Python exceptions
+PyObject *HandleErrors(PyObject *Res = 0);
+
+// Convert a list of strings to a char **
+const char **ListToCharChar(PyObject *List,bool NullTerm = false);
+PyObject *CharCharToList(const char **List,unsigned long Size = 0);
+
+#endif
diff --git a/python/makefile b/python/makefile
new file mode 100644
index 00000000..f8639c93
--- /dev/null
+++ b/python/makefile
@@ -0,0 +1,21 @@
+# -*- make -*-
+BASE=..
+SUBDIR=python
+
+# Bring in the default rules
+include ../buildlib/defaults.mak
+
+# The apt_pkg module
+MODULE=apt_pkg
+SLIBS = -lapt-pkg
+LIB_MAKES = apt-pkg/makefile
+SOURCE = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \
+ cache.cc pkgrecords.cc
+include $(PYTHON_H)
+
+# The apt_int module..
+MODULE=apt_inst
+SLIBS = -lapt-inst -lapt-pkg
+LIB_MAKES = apt-inst/makefile
+SOURCE = apt_instmodule.cc generic.cc
+include $(PYTHON_H)
diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc
new file mode 100644
index 00000000..3128365a
--- /dev/null
+++ b/python/pkgrecords.cc
@@ -0,0 +1,119 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: pkgrecords.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ Package Records - Wrapper for the package records functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/pkgrecords.h>
+
+#include <python/Python.h>
+ /*}}}*/
+
+struct PkgRecordsStruct
+{
+ pkgRecords Records;
+ pkgRecords::Parser *Last;
+
+ PkgRecordsStruct(pkgCache *Cache) : Records(*Cache), Last(0) {};
+ PkgRecordsStruct() : Records(*(pkgCache *)0) {abort();}; // G++ Bug..
+};
+
+// PkgRecords Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyMethodDef PkgRecordsMethods[];
+
+static PyObject *PkgRecordsAttr(PyObject *Self,char *Name)
+{
+ PkgRecordsStruct &Struct = GetCpp<PkgRecordsStruct>(Self);
+
+ if (Struct.Last != 0)
+ {
+ if (strcmp("FileName",Name) == 0)
+ return CppPyString(Struct.Last->FileName());
+ else if (strcmp("MD5Hash",Name) == 0)
+ return CppPyString(Struct.Last->MD5Hash());
+ else if (strcmp("SourcePkg",Name) == 0)
+ return CppPyString(Struct.Last->SourcePkg());
+ else if (strcmp("Maintainer",Name) == 0)
+ return CppPyString(Struct.Last->Maintainer());
+ else if (strcmp("ShortDesc",Name) == 0)
+ return CppPyString(Struct.Last->ShortDesc());
+ else if (strcmp("LongDesc",Name) == 0)
+ return CppPyString(Struct.Last->LongDesc());
+ else if (strcmp("Name",Name) == 0)
+ return CppPyString(Struct.Last->Name());
+ }
+
+ return Py_FindMethod(PkgRecordsMethods,Self,Name);
+}
+
+static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args)
+{
+ PkgRecordsStruct &Struct = GetCpp<PkgRecordsStruct>(Self);
+
+ PyObject *PkgFObj;
+ long int Index;
+ if (PyArg_ParseTuple(Args,"(O!l)",&PackageFileType,&PkgFObj,&Index) == 0)
+ return 0;
+
+ // Get the index and check to make sure it is reasonable
+ pkgCache::PkgFileIterator &PkgF = GetCpp<pkgCache::PkgFileIterator>(PkgFObj);
+ pkgCache *Cache = PkgF.Cache();
+ if (Cache->DataEnd() <= Cache->VerFileP + Index + 1 ||
+ Cache->VerFileP[Index].File != PkgF.Index())
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+
+ // Do the lookup
+ Struct.Last = &Struct.Records.Lookup(pkgCache::VerFileIterator(*Cache,Cache->VerFileP+Index));
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyMethodDef PkgRecordsMethods[] =
+{
+ {"Lookup",PkgRecordsLookup,METH_VARARGS,"Changes to a new package"},
+ {}
+};
+
+PyTypeObject PkgRecordsType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgRecords", // tp_name
+ sizeof(CppOwnedPyObject<PkgRecordsStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<PkgRecordsStruct>, // tp_dealloc
+ 0, // tp_print
+ PkgRecordsAttr, // 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
+};
+
+ /*}}}*/
+
+PyObject *GetPkgRecords(PyObject *Self,PyObject *Args)
+{
+ PyObject *Owner;
+ if (PyArg_ParseTuple(Args,"O!",&PkgCacheType,&Owner) == 0)
+ return 0;
+
+ return HandleErrors(CppOwnedPyObject_NEW<PkgRecordsStruct>(Owner,&PkgRecordsType,
+ GetCpp<pkgCache *>(Owner)));
+}
+
diff --git a/python/string.cc b/python/string.cc
new file mode 100644
index 00000000..7564899b
--- /dev/null
+++ b/python/string.cc
@@ -0,0 +1,96 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: string.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ string - Mappings for the string functions that are worthwile for
+ Python users
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_pkgmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/strutl.h>
+
+#include <python/Python.h>
+ /*}}}*/
+
+// Templated function /*{{{*/
+/* Macro for the generic string in string out function */
+#define MkStr(Python,CFunc) \
+PyObject *Python(PyObject *Self,PyObject *Args) \
+{ \
+ char *Str = 0; \
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0) \
+ return 0; \
+ return CppPyString(CFunc(Str)); \
+}
+
+#define MkInt(Python,CFunc) \
+PyObject *Python(PyObject *Self,PyObject *Args) \
+{ \
+ int Val = 0; \
+ if (PyArg_ParseTuple(Args,"i",&Val) == 0) \
+ return 0; \
+ return CppPyString(CFunc(Val)); \
+}
+
+MkStr(StrDeQuote,DeQuoteString);
+MkStr(StrBase64Encode,Base64Encode);
+MkStr(StrURItoFileName,URItoFileName);
+
+//MkFloat(StrSizeToStr,SizeToStr);
+MkInt(StrTimeToStr,TimeToStr);
+MkInt(StrTimeRFC1123,TimeRFC1123);
+ /*}}}*/
+
+// Other String functions /*{{{*/
+PyObject *StrSizeToStr(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+ if (PyInt_Check(Obj))
+ return CppPyString(SizeToStr(PyInt_AS_LONG(Obj)));
+ if (PyFloat_Check(Obj))
+ return CppPyString(SizeToStr(PyFloat_AS_DOUBLE(Obj)));
+
+ PyErr_SetString(PyExc_TypeError,"Only understand integers and floats");
+ return 0;
+}
+
+PyObject *StrQuoteString(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ char *Bad = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Str,&Bad) == 0)
+ return 0;
+ return CppPyString(QuoteString(Str,Bad));
+}
+
+PyObject *StrStringToBool(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+ return Py_BuildValue("i",StringToBool(Str));
+}
+
+PyObject *StrStrToTime(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+
+ time_t Result;
+ if (StrToTime(Str,Result) == false)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return Py_BuildValue("i",Result);
+}
+ /*}}}*/
diff --git a/python/tag.cc b/python/tag.cc
new file mode 100644
index 00000000..da151832
--- /dev/null
+++ b/python/tag.cc
@@ -0,0 +1,445 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: tag.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ Tag - Binding for the RFC 822 tag file parser
+
+ Upon reflection I have make the TagSection wrapper look like a map..
+ The other option was to use a sequence (which nicely matches the internal
+ storage) but really makes no sense to a Python Programmer.. One
+ specialized lookup is provided, the FindFlag lookup - as well as the
+ usual set of duplicate things to match the C++ interface.
+
+ The TagFile interface is also slightly different, it has a built in
+ internal TagSection object that is used. Do not hold onto a reference
+ to a TagSection and let TagFile go out of scope! The underlying storage
+ for the section will go away and it will seg.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#define _GNU_SOURCE
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/tagfile.h>
+
+#include <stdio.h>
+#include <python/Python.h>
+ /*}}}*/
+static PyMethodDef TagSecMethods[];
+static PyMethodDef TagFileMethods[];
+
+/* We need to keep a private copy of the data.. */
+struct TagSecData : public CppPyObject<pkgTagSection>
+{
+ char *Data;
+};
+
+struct TagFileData : public PyObject
+{
+ pkgTagFile Object;
+ PyObject *File;
+ TagSecData *Section;
+ FileFd Fd;
+};
+
+// TagSecGetAttr - Get an attribute - variable/method /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static PyObject *TagSecGetAttr(PyObject *Self,char *Name)
+{
+ return Py_FindMethod(TagSecMethods,Self,Name);
+}
+ /*}}}*/
+// TagFileGetAttr - Get an attribute - variable/method /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static PyObject *TagFileGetAttr(PyObject *Self,char *Name)
+{
+ if (strcmp("Section",Name) == 0)
+ {
+ PyObject *Obj = ((TagFileData *)Self)->Section;
+ Py_INCREF(Obj);
+ return Obj;
+ }
+
+ return Py_FindMethod(TagFileMethods,Self,Name);
+}
+ /*}}}*/
+// TagSecFree - Free a Tag Section /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void TagSecFree(PyObject *Obj)
+{
+ TagSecData *Self = (TagSecData *)Obj;
+ delete [] Self->Data;
+ CppDealloc<pkgTagSection>(Obj);
+}
+ /*}}}*/
+// TagFileFree - Free a Tag File /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void TagFileFree(PyObject *Obj)
+{
+ TagFileData *Self = (TagFileData *)Obj;
+ Py_DECREF((PyObject *)Self->Section);
+ Self->Object.~pkgTagFile();
+ Self->Fd.~FileFd();
+ Py_DECREF(Self->File);
+ PyMem_DEL(Obj);
+}
+ /*}}}*/
+
+// Tag Section Wrappers /*{{{*/
+static char *doc_Find = "Find(Name) -> String/None";
+static PyObject *TagSecFind(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ {
+ if (Default == 0)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return PyString_FromString(Default);
+ }
+ return PyString_FromStringAndSize(Start,Stop-Start);
+}
+
+static char *doc_FindFlag = "FindFlag(Name) -> integer/none";
+static PyObject *TagSecFindFlag(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ unsigned long Flag = 0;
+ if (GetCpp<pkgTagSection>(Self).FindFlag(Name,Flag,1) == false)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return Py_BuildValue("i",Flag);
+}
+
+// Map access, operator []
+static PyObject *TagSecMap(PyObject *Self,PyObject *Arg)
+{
+ if (PyString_Check(Arg) == 0)
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return 0;
+ }
+
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(PyString_AsString(Arg),Start,Stop) == false)
+ {
+ PyErr_SetString(PyExc_KeyError,PyString_AsString(Arg));
+ return 0;
+ }
+
+ return PyString_FromStringAndSize(Start,Stop-Start);
+}
+
+// len() operation
+static int TagSecLength(PyObject *Self)
+{
+ pkgTagSection &Sec = GetCpp<pkgTagSection>(Self);
+ return Sec.Count();
+}
+
+// Look like a mapping
+static char *doc_Keys = "keys() -> List";
+static PyObject *TagSecKeys(PyObject *Self,PyObject *Args)
+{
+ pkgTagSection &Tags = GetCpp<pkgTagSection>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ for (unsigned int I = 0; I != Tags.Count(); I++)
+ {
+ const char *Start;
+ const char *Stop;
+ Tags.Get(Start,Stop,I);
+ const char *End = Start;
+ for (; End < Stop && *End != ':'; End++);
+
+ PyObject *Obj;
+ PyList_Append(List,Obj = PyString_FromStringAndSize(Start,End-Start));
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static char *doc_Exists = "Exists(Name) -> integer";
+static PyObject *TagSecExists(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ return Py_BuildValue("i",0);
+ return Py_BuildValue("i",1);
+}
+
+static char *doc_Bytes = "Bytes() -> integer";
+static PyObject *TagSecBytes(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ return Py_BuildValue("i",GetCpp<pkgTagSection>(Self).size());
+}
+
+static PyObject *TagSecStr(PyObject *Self)
+{
+ const char *Start;
+ const char *Stop;
+ GetCpp<pkgTagSection>(Self).GetSection(Start,Stop);
+ return PyString_FromStringAndSize(Start,Stop-Start);
+}
+ /*}}}*/
+// TagFile Wrappers /*{{{*/
+static char *doc_Step = "Step() -> Integer\n0 means EOF.";
+static PyObject *TagFileStep(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ TagFileData &Obj = *(TagFileData *)Self;
+ if (Obj.Object.Step(Obj.Section->Object) == false)
+ return HandleErrors(Py_BuildValue("i",0));
+
+ return HandleErrors(Py_BuildValue("i",1));
+}
+
+static char *doc_Offset = "Offset() -> Integer";
+static PyObject *TagFileOffset(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+ return Py_BuildValue("i",((TagFileData *)Self)->Object.Offset());
+}
+
+static char *doc_Jump = "Jump(Offset) -> Integer";
+static PyObject *TagFileJump(PyObject *Self,PyObject *Args)
+{
+ int Offset;
+ if (PyArg_ParseTuple(Args,"i",&Offset) == 0)
+ return 0;
+
+ TagFileData &Obj = *(TagFileData *)Self;
+ if (Obj.Object.Jump(Obj.Section->Object,Offset) == false)
+ return HandleErrors(Py_BuildValue("i",0));
+
+ return HandleErrors(Py_BuildValue("i",1));
+}
+ /*}}}*/
+// ParseSection - Parse a single section from a tag file /*{{{*/
+// ---------------------------------------------------------------------
+char *doc_ParseSection ="ParseSection(Text) -> SectionObject";
+PyObject *ParseSection(PyObject *self,PyObject *Args)
+{
+ char *Data;
+ if (PyArg_ParseTuple(Args,"s",&Data) == 0)
+ return 0;
+
+ // Create the object..
+ TagSecData *New = PyObject_NEW(TagSecData,&TagSecType);
+ new (&New->Object) pkgTagSection();
+ New->Data = new char[strlen(Data)+2];
+ snprintf(New->Data,strlen(Data)+2,"%s\n",Data);
+
+ if (New->Object.Scan(New->Data,strlen(New->Data)) == false)
+ {
+ cerr << New->Data << endl;
+ Py_DECREF((PyObject *)New);
+ PyErr_SetString(PyExc_ValueError,"Unable to parse section data");
+ return 0;
+ }
+
+ New->Object.Trim();
+
+ return New;
+}
+ /*}}}*/
+// ParseTagFile - Parse a tagd file /*{{{*/
+// ---------------------------------------------------------------------
+/* This constructs the parser state. */
+char *doc_ParseTagFile = "ParseTagFile(File) -> TagFile";
+PyObject *ParseTagFile(PyObject *self,PyObject *Args)
+{
+ PyObject *File;
+ if (PyArg_ParseTuple(Args,"O!",&PyFile_Type,&File) == 0)
+ return 0;
+
+ TagFileData *New = PyObject_NEW(TagFileData,&TagFileType);
+ new (&New->Fd) FileFd(fileno(PyFile_AsFile(File)),false);
+ New->File = File;
+ Py_INCREF(New->File);
+ new (&New->Object) pkgTagFile(&New->Fd);
+
+ // Create the section
+ New->Section = PyObject_NEW(TagSecData,&TagSecType);
+ new (&New->Section->Object) pkgTagSection();
+ New->Section->Data = 0;
+
+ return HandleErrors(New);
+}
+ /*}}}*/
+// RewriteSection - Rewrite a section.. /*{{{*/
+// ---------------------------------------------------------------------
+/* An interesting future extension would be to add a user settable
+ order list */
+char *doc_RewriteSection =
+"RewriteSection(Section,Order,RewriteList) -> String\n"
+"\n"
+"The section rewriter allows a section to be taken in, have fields added,\n"
+"removed or changed and then put back out. During this process the fields\n"
+"within the section are sorted to corrispond to a proper order. Order is a\n"
+"list of field names with their proper capitialization.\n"
+"apt_pkg.RewritePackageOrder and apt_pkg.RewriteSourceOrder are two predefined\n"
+"orders.\n"
+"RewriteList is a list of tuples. Each tuple is of the form:\n"
+" (Tag,NewValue[,RenamedTo])\n"
+"Tag specifies the tag in the source section. NewValue is the new value of\n"
+"that tag and the optional RenamedTo field can cause the tag to be changed.\n"
+"If NewValue is None then the tag is removed\n"
+"Ex. ('Source','apt','Package') is used for .dsc files.";
+PyObject *RewriteSection(PyObject *self,PyObject *Args)
+{
+ PyObject *Section;
+ PyObject *Order;
+ PyObject *Rewrite;
+ if (PyArg_ParseTuple(Args,"O!O!O!",&TagSecType,&Section,
+ &PyList_Type,&Order,&PyList_Type,&Rewrite) == 0)
+ return 0;
+
+ // Convert the order list
+ const char **OrderList = ListToCharChar(Order,true);
+
+ // Convert the Rewrite list.
+ TFRewriteData *List = new TFRewriteData[PySequence_Length(Rewrite)+1];
+ memset(List,0,sizeof(*List)*(PySequence_Length(Rewrite)+1));
+ for (int I = 0; I != PySequence_Length(Rewrite); I++)
+ {
+ List[I].NewTag = 0;
+ if (PyArg_ParseTuple(PySequence_GetItem(Rewrite,I),"sz|s",
+ &List[I].Tag,&List[I].Rewrite,&List[I].NewTag) == 0)
+ {
+ delete [] OrderList;
+ delete [] List;
+ return 0;
+ }
+ }
+
+ /* This is a glibc extension.. If not running on glibc I'd just take
+ this whole function out, it is probably infrequently used */
+ char *bp = 0;
+ size_t size;
+ FILE *F = open_memstream (&bp, &size);
+
+ // Do the rewrite
+ bool Res = TFRewrite(F,GetCpp<pkgTagSection>(Section),OrderList,List);
+ delete [] OrderList;
+ delete [] List;
+ fclose(F);
+
+ if (Res == false)
+ {
+ free(bp);
+ return HandleErrors();
+ }
+
+ // Return the string
+ PyObject *ResObj = PyString_FromStringAndSize(bp,size);
+ free(bp);
+ return HandleErrors(ResObj);
+}
+ /*}}}*/
+
+// Method table for the Tag Section object
+static PyMethodDef TagSecMethods[] =
+{
+ // Query
+ {"Find",TagSecFind,METH_VARARGS,doc_Find},
+ {"FindFlag",TagSecFindFlag,METH_VARARGS,doc_FindFlag},
+ {"Bytes",TagSecBytes,METH_VARARGS,doc_Bytes},
+
+ // Python Special
+ {"keys",TagSecKeys,METH_VARARGS,doc_Keys},
+ {"has_key",TagSecExists,METH_VARARGS,doc_Exists},
+ {"get",TagSecFind,METH_VARARGS,doc_Find},
+ {}
+};
+
+// Type for a Tag Section
+PyMappingMethods TagSecMapMeth = {TagSecLength,TagSecMap,0};
+PyTypeObject TagSecType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "TagSection", // tp_name
+ sizeof(TagSecData), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ TagSecFree, // tp_dealloc
+ 0, // tp_print
+ TagSecGetAttr, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ &TagSecMapMeth, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ TagSecStr, // tp_str
+};
+
+// Method table for the Tag File object
+static PyMethodDef TagFileMethods[] =
+{
+ // Query
+ {"Step",TagFileStep,METH_VARARGS,doc_Step},
+ {"Offset",TagFileOffset,METH_VARARGS,doc_Offset},
+ {"Jump",TagFileJump,METH_VARARGS,doc_Jump},
+
+ {}
+};
+
+// Type for a Tag File
+PyTypeObject TagFileType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "TagFile", // tp_name
+ sizeof(TagFileData), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ TagFileFree, // tp_dealloc
+ 0, // tp_print
+ TagFileGetAttr, // 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
+};