Bug#623485: python-apt: please add bindings pkgOrderList

2011-04-28 Thread Julian Andres Klode
On Mi, 2011-04-27 at 19:28 +0200, Pietro Abate wrote:
 In the long term maybe the correct solution to all this mambo-jumbo would be 
 to
 implement the packageManager bindings as a virtual class with a default on 
 dpkg
 as it is now, but giving the possibility to override from the python side the
 Install/Configure/Remove/Go functions in order to hack into the pkgmanager
 algorithm cleanly. I'm not sure this is possible given the current 
 architecture...
This patch implements this. It breaks the C++ API for embedding
python-apt though, so we may need a slightly different solution on the C
++ side, but the Python side works. I am also attaching an example show
casing this. 

I try to get this PackageManager feature implemented more cleanly
tomorrow. Until then, test the patch!

-- 
Julian Andres Klode  - Debian Developer, Ubuntu Member

See http://wiki.debian.org/JulianAndresKlode and http://jak-linux.org/.

=== modified file 'python/pkgmanager.cc'
--- python/pkgmanager.cc	2011-04-12 09:38:25 +
+++ python/pkgmanager.cc	2011-04-28 14:08:30 +
@@ -2,7 +2,7 @@
 // $Id: acquire.cc,v 1.1 2003/06/03 03:03:23 mvo Exp $
 /* ##
 
-   PkgManager - Wrapper for the pkgPackageManager code
+   PkgManager - Wrapper for the PyPkgManager code
 
# */
 
@@ -17,9 +17,89 @@
 #include apt-pkg/acquire.h
 #include apt-pkg/init.h
 #include apt-pkg/configuration.h
+#include apt-pkg/dpkgpm.h
 
 #include iostream
 
+struct CppPyRef {
+	PyObject *o;
+	CppPyRef(const CppPyRef o) { Py_XINCREF(o); this-o = o; }
+	CppPyRef(PyObject *o) : o(o) {}
+	~CppPyRef() { Py_XDECREF(o); }
+	operator PyObject *() const { return o; }
+	PyObject *operator-() const { return o; }
+};
+
+
+
+struct PyPkgManager : public pkgDPkgPM {
+	
+	bool res(CppPyRef result) {
+		if (result == NULL) {
+			std::cerr  Error in function:   std::endl;
+			PyErr_Print();
+			PyErr_Clear();
+			return false;
+		}
+		return (result != NULL 
+		(result == Py_None || PyObject_IsTrue(result) == 1));
+	}
+	
+	PyPkgManager(pkgDepCache *Cache) : pkgDPkgPM(Cache) {};
+	PyObject *GetPyPkg(const PkgIterator Pkg) {
+		static PyObject * const cache = 0; /*FIXME*/
+		return PyPackage_FromCpp(Pkg, true, cache);
+	}
+protected:
+	/* Call through to Python */
+	virtual bool Install(PkgIterator Pkg,string File) {
+		return res(PyObject_CallMethod(pyinst, install, (NN), 
+		   GetPyPkg(Pkg),
+		   CppPyString(File)));
+	}
+	virtual bool Configure(PkgIterator Pkg) {
+		return res(PyObject_CallMethod(pyinst, configure, (N), 
+		   GetPyPkg(Pkg)));
+	}
+	virtual bool Remove(PkgIterator Pkg,bool Purge = false) {
+		return res(PyObject_CallMethod(pyinst, remove, (NN), 
+		   GetPyPkg(Pkg),
+		   PyBool_FromLong(Purge)));
+	}
+	virtual bool Go(int StatusFd=-1) {
+		return res(PyObject_CallMethod(pyinst, go, (i),
+		   StatusFd));
+	}
+	virtual void Reset() {
+		CppPyRef(PyObject_CallMethod(pyinst, reset, NULL));
+	}
+	
+public:
+	/* Those call the protected functions from the parent class */
+	bool callInstall(PkgIterator Pkg,string File) {
+		return pkgDPkgPM::Install(Pkg, File);
+	}
+	
+	bool callRemove(PkgIterator Pkg, bool Purge) {
+		return pkgDPkgPM::Remove(Pkg, Purge);
+	}
+	bool callGo(int StatusFd=-1) {
+		return pkgDPkgPM::Go(StatusFd);
+	}
+	void callReset() {
+		return pkgDPkgPM::Reset();
+	}
+	bool callConfigure(PkgIterator Pkg) {
+		return pkgDPkgPM::Configure(Pkg);
+	}
+	
+	pkgOrderList *getOrderList() {
+		return pkgPackageManager::List;
+	}
+	
+	PyObject *pyinst;
+};
+
 static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
 {
PyObject *Owner;
@@ -28,10 +108,12 @@ static PyObject *PkgManagerNew(PyTypeObj
Owner) == 0)
   return 0;
 
-   pkgPackageManager *pm = _system-CreatePM(GetCpppkgDepCache*(Owner));
+   PyPkgManager *pm = new PyPkgManager(GetCpppkgDepCache*(Owner));
 
-   CppPyObjectpkgPackageManager* *PkgManagerObj =
-	   CppPyObject_NEWpkgPackageManager*(NULL, type,pm);
+   CppPyObjectPyPkgManager* *PkgManagerObj =
+	   CppPyObject_NEWPyPkgManager*(NULL, type,pm);
+	   
+   pm-pyinst = PkgManagerObj;
 
return PkgManagerObj;
 }
@@ -46,10 +128,65 @@ PyObject *GetPkgManager(PyObject *Self,P
 }
 #endif
 
+static PyObject *PkgManagerInstall(PyObject *Self,PyObject *Args)
+{
+   PyPkgManager *pm = GetCppPyPkgManager*(Self);
+   PyObject *pkg;
+   const char *file;
+
+   if (PyArg_ParseTuple(Args, O!s, PyPackage_Type,pkg, file) == 0)
+  return 0;
+
+   return HandleErrors(PyBool_FromLong(pm-callInstall(PyPackage_ToCpp(pkg), file)));
+}
+
+
+static PyObject *PkgManagerConfigure(PyObject *Self,PyObject *Args)
+{
+   PyPkgManager *pm = GetCppPyPkgManager*(Self);
+   PyObject *pkg;
+
+   if 

Bug#623485: python-apt: please add bindings pkgOrderList

2011-04-27 Thread Julian Andres Klode
On Do, 2011-04-21 at 16:57 +0200, Pietro Abate wrote:
 hello
 
 On Thu, Apr 21, 2011 at 03:53:39PM +0200, Julian Andres Klode wrote:
  On Mi, 2011-04-20 at 19:06 +0200, Pietro Abate wrote:
   This is a request to add a new binding to the class pkgOrderList of apt.
   The idea is to allow to compute and set the pkgOrderList independently
   and reason about it.

   Provided a bit of guidance (I'm not very familiar with the apt python
   bindings), we'll be happy to provide a patch.
  I'm going to write it next week, the 0.8.0~exp4 release next
  Tuesday/Wednesday would then include it.
 
 thank you ! this is fantastic !
Attaching a diff for review. Also see
http://apt.alioth.debian.org/python-apt-doc/library/apt_pkg.html#apt_pkg.OrderList

Note that this only adds a new OrderList class, it does not provide any
integration with PackageManager. If you wish to have integration, please
tell me how you'd like it to be.

-- 
Julian Andres Klode  - Debian Developer, Ubuntu Member

See http://wiki.debian.org/JulianAndresKlode and http://jak-linux.org/.

=== modified file 'debian/changelog'
--- debian/changelog	2011-04-21 13:34:01 +
+++ debian/changelog	2011-04-27 10:57:27 +
@@ -1,3 +1,9 @@
+python-apt (0.8.0~exp4) UNRELEASED; urgency=low
+
+  * apt_pkg: Add OrderList, wanted for mancoosi (Closes: #623485)
+
+ -- Julian Andres Klode j...@debian.org  Wed, 27 Apr 2011 12:55:59 +0200
+
 python-apt (0.8.0~exp3) experimental; urgency=low
 
   [ Stéphane Graber ]

=== modified file 'doc/source/c++/api.rst'
--- doc/source/c++/api.rst	2011-04-05 14:11:34 +
+++ doc/source/c++/api.rst	2011-04-27 10:40:10 +
@@ -622,6 +622,34 @@ IndexFile (pkgIndexFile)
 Return the :ctype:`pkgIndexFile` pointer contained in the Python object
 *object*.
 
+OrderList (pkgOrderList)
+---
+.. cvar:: PyTypeObject PyOrderList_Type
+
+The type object for :class:`apt_pkg.OrderList` objects.
+
+.. cfunction:: int PyOrderList_Check(PyObject *object)
+
+Check that the object *object* is an :class:`apt_pkg.OrderList` object, or
+a subclass thereof.
+
+.. cfunction:: int PyOrderList_CheckExact(PyObject *object)
+
+Check that the object *object* is an :class:`apt_pkg.OrderList` object
+and no subclass thereof.
+
+.. cfunction:: PyObject* PyOrderList_FromCpp(pkgOrderList *cpp, bool delete, PyObject *owner)
+
+Create a new :class:`apt_pkg.OrderList` object from the :ctype:`pkgOrderList`
+pointer given by the parameter *cpp*. If the parameter *delete* is
+true, the object pointed to by *cpp* will be deleted when the reference
+count of the returned object reaches 0. The owner must be a
+:class:`apt_pkg.DepCache` object.
+
+.. cfunction:: pkgOrderList* PyOrderList_ToCpp(PyObject *object)
+
+Return the :ctype:`pkgOrderList` pointer contained in the Python object
+*object*.
 
 PackageManager (pkgPackageManager)
 --

=== modified file 'doc/source/library/apt_pkg.rst'
--- doc/source/library/apt_pkg.rst	2011-04-21 12:21:22 +
+++ doc/source/library/apt_pkg.rst	2011-04-27 11:04:30 +
@@ -422,6 +422,99 @@ Installing with :class:`PackageManager`
 
 A constant for checking whether the the result of the call to
 :meth:`do_install` is 'incomplete'.
+
+Installation ordering with :class:`OrderList`
+^
+
+.. class:: OrderList(depcache: DepCache)
+
+	Represent a :ctype:`pkgOrderList`, used for installation
+	ordering. This class provides several methods and attributes,
+	is complicated and should not be used by normal programs.
+	
+	.. versionadded:: 0.8.0
+	
+	This class is a sequence and supports the following operations:
+	
+	.. describe:: list[index]
+	
+		Get the package at the given index in the list. Negative
+		index is supported.
+		
+	.. describe:: len(list)
+	
+		The length of the list.
+		
+	It also supports the append() method from :class:`list`:
+	
+	.. method:: append(pkg: Package)
+	
+		Append a new package to the end of the list. Please note that
+		you may not append a package twice, as only as much packages
+		as in the cache can be added.
+		
+	The class also defines several specific attributes and methods,
+	to be described hereinafter.
+		
+	.. method:: score(pkg: Package)
+	
+		Return the score of the package. Packages are basically
+		ordered by descending score.
+		
+	This class allows flags to be set on packages. Those flags are:
+	
+	.. attribute:: FLAG_ADDED
+	.. attribute:: FLAG_ADD_PENDING
+	.. attribute:: FLAG_IMMEDIATE
+	.. attribute:: FLAG_LOOP
+	.. attribute:: FLAG_UNPACKED
+	.. attribute:: FLAG_CONFIGURED
+	.. attribute:: FLAG_REMOVED
+	.. attribute:: FLAG_STATES_MASK
+	
+		Same as ``FLAG_UNPACKED | FLAG_CONFIGURED | FLAG_REMOVED``
+		
+	.. attribute:: FLAG_IN_LIST
+	.. attribute:: FLAG_AFTER
+	
+	The methods to work with those flags are:
+		
+	.. method:: flag(pkg: Package, flag: int[, unset_flags: int])
+
+		Flag a package. Sets the flags 

Bug#623485: python-apt: please add bindings pkgOrderList

2011-04-27 Thread Pietro Abate
Hello Julian,

On Wed, Apr 27, 2011 at 01:07:49PM +0200, Julian Andres Klode wrote:
 On Do, 2011-04-21 at 16:57 +0200, Pietro Abate wrote:
  On Thu, Apr 21, 2011 at 03:53:39PM +0200, Julian Andres Klode wrote:
   On Mi, 2011-04-20 at 19:06 +0200, Pietro Abate wrote:
This is a request to add a new binding to the class pkgOrderList of apt.
The idea is to allow to compute and set the pkgOrderList independently
and reason about it.
 Attaching a diff for review. Also see
 http://apt.alioth.debian.org/python-apt-doc/library/apt_pkg.html#apt_pkg.OrderList
 
 Note that this only adds a new OrderList class, it does not provide any
 integration with PackageManager. If you wish to have integration, please
 tell me how you'd like it to be.

This is great. I had a look at the code and doc and it seems good so
far. I re-read the apt-pkg code regarding the packagemanager class and
maybe I've a suggestion on a possible integration with the work you have
done.

the packagemanger has a number of virtual methods that are instantiated
in apt-pkg/deb/dpkgpm.cc . These methods are protected in the
packagemaneger class :

// The Actual installation implementation
virtual bool Install(PkgIterator /*Pkg*/,string /*File*/) {return false;};
virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
virtual bool Go(int statusFd=-1) {return true;};
virtual void Reset() {};

the packagemaneger object is created in cmdline/apt-get.cc by a call to 
this function:

SPtrpkgPackageManager PM= _system-CreatePM(Cache);

In apt-get, if Simulated is specified, the package manager will be
instantiated as a pkgSimulate object (that is a concrete implementation of
packageManager ).

The problem is that this class does not save the installation plan anywhere it 
only
prints it on screen.

My proposal of integration will be very simple. We can create a new subclass of
packageManager , say pkgPlan that will implement install, configure, remove,
etc and instead of printing on stdout the actions as in pkgSimulate, will save
this information in a list that can be for our purposes. Since the dpkg
commands are built in yet another packageManager object derived from
apt-pkg/deb/dpkgpm.cc I don't think it will be easy to get a trace of what dpkg
would have done if invoked (even this would be great...). But for the moment I
think the list Inst/Conf/Rem will be enough.  The real list of dpkg commands
can be obtained (not in simulation mode) with the debug variable:
Debug::pkgDPkgPM=true

In the long term maybe the correct solution to all this mambo-jumbo would be to
implement the packageManager bindings as a virtual class with a default on dpkg
as it is now, but giving the possibility to override from the python side the
Install/Configure/Remove/Go functions in order to hack into the pkgmanager
algorithm cleanly. I'm not sure this is possible given the current 
architecture...

As it is the OrderList class will allow to easily reimplement the backend and
in theory to completely bypass the apt-pkg/deb/dpkgpm.cc and perform the
installation via another package manager, say rpm...

thanks again for your great support.

pietro

-- 

http://en.wikipedia.org/wiki/Posting_style



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#623485: python-apt: please add bindings pkgOrderList

2011-04-26 Thread Julian Andres Klode
On Do, 2011-04-21 at 16:57 +0200, Pietro Abate wrote:
 hello
 
 On Thu, Apr 21, 2011 at 03:53:39PM +0200, Julian Andres Klode wrote:
  On Mi, 2011-04-20 at 19:06 +0200, Pietro Abate wrote:
   This is a request to add a new binding to the class pkgOrderList of apt.
   The idea is to allow to compute and set the pkgOrderList independently
   and reason about it.
   
   At the moment the only way to compute (via apt-get) the installation
   plan is to execute it and print a debug trace of it. 
   
   For the mancoosi project we would like to compute the plan before
   executing it and to simulate the installation in order to detect
   possible problems in the installation scripts.
   
   I'm aware that this binding will export a read-only object and that the
   installation plan will be recomputed by apt-get. This will be sufficient
   for our goals.
  As far as I can tell, the object would be read-write. You fill the list,
  then you order it, and then you read it again. So, shall I bind just the
  pkgOrderList class or do you want anything related as well?
 
 If I read the code correctly, you initialize the pkgOrderList with the
 cache (that contains the packages marked to be installed/removed) and
 then you read back the list of ordered packages. In this sense the
 object is of course read/write.
You could also add some packages, order, add some more.

 
 My remark was related how the pkgOrderList class is used in the module
 packageManager where the orderedlist is protected. Without modifying
 the API of the packageManager it is not possible at the moment to pass
 to the installer the installation plan. This is also because the
 computation of the installation plan is intertwined with the
 real installation itself (for performances reasons I presume).
 
 What we need is a way to build the installation plan from the cache
 (initialized with the packages that are going to be installed/removed).
 There are a bunch of protected functions in packageManager that use the
 orderedList, but as far as I can see they are all protected... 
 
 Once the pkgOrderList class will be available I think I'll need to
 reimplement in my application the logic of few functions in
 packageManager to (re)-build the installation plan (aka the order in
 which dpkg is called to pre-configure / unpack / configure / install /
 remove / *-hooks / ext ).

But OrderList being available in the Python bindings only brings you the
ordering itself, no integration whatsoever with PackageManager. All the
interesting stuff in PackageManager is protected and thus not bound.

And binding OrderList is not fun, it's severely under-documented. That's
a pain to bind: Because the bindings are fully documented, I need to
play detective and find out what functions and values are supposed to
mean...

-- 
Julian Andres Klode  - Debian Developer, Ubuntu Member

See http://wiki.debian.org/JulianAndresKlode and http://jak-linux.org/.





-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#623485: python-apt: please add bindings pkgOrderList

2011-04-21 Thread Julian Andres Klode
On Mi, 2011-04-20 at 19:06 +0200, Pietro Abate wrote:
 Package: python-apt
 Version: 0.7.100.3+b1
 Severity: wishlist
 
 
 Hello,
 
 This is a request to add a new binding to the class pkgOrderList of apt.
 The idea is to allow to compute and set the pkgOrderList independently
 and reason about it.
 
 At the moment the only way to compute (via apt-get) the installation
 plan is to execute it and print a debug trace of it. 
 
 For the mancoosi project we would like to compute the plan before
 executing it and to simulate the installation in order to detect
 possible problems in the installation scripts.
 
 I'm aware that this binding will export a read-only object and that the
 installation plan will be recomputed by apt-get. This will be sufficient
 for our goals.
As far as I can tell, the object would be read-write. You fill the list,
then you order it, and then you read it again. So, shall I bind just the
pkgOrderList class or do you want anything related as well?

 Provided a bit of guidance (I'm not very familiar with the apt python
 bindings), we'll be happy to provide a patch.
I'm going to write it next week, the 0.8.0~exp4 release next
Tuesday/Wednesday would then include it.

-- 
Julian Andres Klode  - Debian Developer, Ubuntu Member

See http://wiki.debian.org/JulianAndresKlode and http://jak-linux.org/.





-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#623485: python-apt: please add bindings pkgOrderList

2011-04-21 Thread Pietro Abate
hello

On Thu, Apr 21, 2011 at 03:53:39PM +0200, Julian Andres Klode wrote:
 On Mi, 2011-04-20 at 19:06 +0200, Pietro Abate wrote:
  This is a request to add a new binding to the class pkgOrderList of apt.
  The idea is to allow to compute and set the pkgOrderList independently
  and reason about it.
  
  At the moment the only way to compute (via apt-get) the installation
  plan is to execute it and print a debug trace of it. 
  
  For the mancoosi project we would like to compute the plan before
  executing it and to simulate the installation in order to detect
  possible problems in the installation scripts.
  
  I'm aware that this binding will export a read-only object and that the
  installation plan will be recomputed by apt-get. This will be sufficient
  for our goals.
 As far as I can tell, the object would be read-write. You fill the list,
 then you order it, and then you read it again. So, shall I bind just the
 pkgOrderList class or do you want anything related as well?

If I read the code correctly, you initialize the pkgOrderList with the
cache (that contains the packages marked to be installed/removed) and
then you read back the list of ordered packages. In this sense the
object is of course read/write.

My remark was related how the pkgOrderList class is used in the module
packageManager where the orderedlist is protected. Without modifying
the API of the packageManager it is not possible at the moment to pass
to the installer the installation plan. This is also because the
computation of the installation plan is intertwined with the
real installation itself (for performances reasons I presume).

What we need is a way to build the installation plan from the cache
(initialized with the packages that are going to be installed/removed).
There are a bunch of protected functions in packageManager that use the
orderedList, but as far as I can see they are all protected... 

Once the pkgOrderList class will be available I think I'll need to
reimplement in my application the logic of few functions in
packageManager to (re)-build the installation plan (aka the order in
which dpkg is called to pre-configure / unpack / configure / install /
remove / *-hooks / ext ).

From my understanding of the apt code this is the easiest way to attain
this goal... and it's also a lot of work that I prefer to do in python
the to ack the c++ code base of apt-get.

  Provided a bit of guidance (I'm not very familiar with the apt python
  bindings), we'll be happy to provide a patch.
 I'm going to write it next week, the 0.8.0~exp4 release next
 Tuesday/Wednesday would then include it.

thank you ! this is fantastic !

regards.
pietro

-- 

http://en.wikipedia.org/wiki/Posting_style



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#623485: python-apt: please add bindings pkgOrderList

2011-04-20 Thread Pietro Abate
Package: python-apt
Version: 0.7.100.3+b1
Severity: wishlist


Hello,

This is a request to add a new binding to the class pkgOrderList of apt.
The idea is to allow to compute and set the pkgOrderList independently
and reason about it.

At the moment the only way to compute (via apt-get) the installation
plan is to execute it and print a debug trace of it. 

For the mancoosi project we would like to compute the plan before
executing it and to simulate the installation in order to detect
possible problems in the installation scripts.

I'm aware that this binding will export a read-only object and that the
installation plan will be recomputed by apt-get. This will be sufficient
for our goals.

Provided a bit of guidance (I'm not very familiar with the apt python
bindings), we'll be happy to provide a patch.

look forward for your feedback.

pietro


-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.32-5-xen-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages python-apt depends on:
ii  apt [libapt-pkg4.10]  0.8.14.1   Advanced front-end for dpkg
ii  apt-utils [libapt-inst1.2]0.8.14.1   APT utility programs
ii  libc6 2.11.2-13  Embedded GNU C Library: Shared lib
ii  libgcc1   1:4.6.0-3  GCC support library
ii  libstdc++64.6.0-3The GNU Standard C++ Library v3
ii  python2.6.6-14   interactive high-level object-orie
ii  python-apt-common 0.7.100.3  Python interface to libapt-pkg (lo
ii  python2.6 2.6.6-8+b1 An interactive high-level object-o
ii  python2.7 2.7.1-6An interactive high-level object-o

Versions of packages python-apt recommends:
ii  iso-codes 3.25-1 ISO language, territory, currency,
ii  lsb-release   3.2-27 Linux Standard Base version report
ii  python2.6 2.6.6-8+b1 An interactive high-level object-o

Versions of packages python-apt suggests:
pn  python-apt-dbg   none  (no description available)
pn  python-apt-doc   none  (no description available)
ii  python-gtk2  2.17.0-4+b2 Python bindings for the GTK+ widge
pn  python-vte   none  (no description available)

-- no debconf information



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org