summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt/cache.py24
-rw-r--r--aptsources/distro.py4
-rw-r--r--debian/changelog40
-rw-r--r--python/progress.cc67
-rw-r--r--python/progress.h17
5 files changed, 125 insertions, 27 deletions
diff --git a/apt/cache.py b/apt/cache.py
index 9982559b..40808abd 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -66,8 +66,32 @@ class Cache(object):
apt_pkg.config.set("Dir", rootdir)
apt_pkg.config.set("Dir::State::status",
rootdir + "/var/lib/dpkg/status")
+ # create required dirs/files when run with special rootdir
+ # automatically
+ self._check_and_create_required_dirs(rootdir)
self.open(progress)
+ def _check_and_create_required_dirs(self, rootdir):
+ """
+ check if the required apt directories/files are there and if
+ not create them
+ """
+ files = ["/var/lib/dpkg/status",
+ "/etc/apt/sources.list",
+ ]
+ dirs = ["/var/lib/dpkg",
+ "/etc/apt/",
+ "/var/cache/apt/archives/partial",
+ "/var/lib/apt/lists/partial",
+ ]
+ for d in dirs:
+ if not os.path.exists(rootdir+d):
+ print "creating: ",rootdir+d
+ os.makedirs(rootdir+d)
+ for f in files:
+ if not os.path.exists(rootdir+f):
+ open(rootdir+f,"w")
+
def _run_callbacks(self, name):
""" internal helper to run a callback """
if name in self._callbacks:
diff --git a/aptsources/distro.py b/aptsources/distro.py
index bbb8ba50..5398d4a3 100644
--- a/aptsources/distro.py
+++ b/aptsources/distro.py
@@ -319,12 +319,12 @@ class Distribution:
if s.type == self.binary_type:
if s.dist not in comps_per_dist:
comps_per_dist[s.dist] = set()
- map(comps_per_dist[s.dist].add, s.comps)
+ map(comps_per_dist[s.dist].add, s.comps)
for s in self.source_code_sources:
if s.type == self.source_type:
if s.dist not in comps_per_sdist:
comps_per_sdist[s.dist] = set()
- map(comps_per_sdist[s.dist].add, s.comps)
+ map(comps_per_sdist[s.dist].add, s.comps)
# check if there is a main source at all
if len(self.main_sources) < 1:
diff --git a/debian/changelog b/debian/changelog
index b2936ba1..e67408ee 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -18,7 +18,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low
mark a package as automatically installed.
* Drop apt_pkg.Cache.open() and apt_pkg.Cache.close(), they cause segfaults
and memory leaks. Simply create a new cache instead.
- * Merge 0.7.10.4 from unstable
+ * Merge 0.7.10.4, 0.7.11.0 from unstable
* debian/control: Update Standards-Version to 3.8.2
* Make AcquireFile a subclass of AcquireItem
* Make ConfigurationPtr,ConfigurationSub subclasses of Configuration.
@@ -47,16 +47,6 @@ python-apt (0.7.92) UNRELEASED; urgency=low
* apt/progress.py: Extract the package name from the status message
(Closes: #532660)
- [ Stephan Peijnik ]
- * apt/progress/__init__.py:
- - add update_status_full() that takes file_size/partial_size as
- additional callback arguments
- - add pulse_items() that takes a addtional "items" tuple that
- gives the user full access to the individual items that are
- fetched
- * python/progress.cc:
- - low level code for update_status_full and pulse_items()
-
-- Julian Andres Klode <jak@debian.org> Wed, 15 Jul 2009 14:56:24 +0200
python-apt (0.7.91) experimental; urgency=low
@@ -97,6 +87,34 @@ python-apt (0.7.90) experimental; urgency=low
-- Julian Andres Klode <jak@debian.org> Wed, 15 Apr 2009 13:47:42 +0200
+python-apt (0.7.11.0) UNRELEASED; urgency=low
+
+ [ Julian Andres Klode ]
+ * data/templates/Debian.info.in: Squeeze will be 6.0, not 5.1
+
+ [ Stephan Peijnik ]
+ * apt/progress/__init__.py:
+ - add update_status_full() that takes file_size/partial_size as
+ additional callback arguments
+ - add pulse_items() that takes a addtional "items" tuple that
+ gives the user full access to the individual items that are
+ fetched
+ * python/progress.cc:
+ - low level code for update_status_full and pulse_items()
+ - better threading support
+
+ [ Michael Vogt ]
+ * aptsources/distro.py:
+ - fix indent error that causes incorrect sources.list additons
+ (LP: #372224)
+ * python/progress.cc:
+ - fix crash in RunSimpleCallback()
+ * apt/cache.py:
+ - when the cache is run with a alternative rootdir, create
+ required dirs/files automatically
+
+ -- Michael Vogt <mvo@debian.org> Mon, 20 Jul 2009 15:35:27 +0200
+
python-apt (0.7.10.4) unstable; urgency=low
[ Michael Vogt ]
diff --git a/python/progress.cc b/python/progress.cc
index 2feba503..3dd104ab 100644
--- a/python/progress.cc
+++ b/python/progress.cc
@@ -30,13 +30,16 @@ bool PyCallbackObj::RunSimpleCallback(const char* method_name,
PyObject *method = PyObject_GetAttrString(callbackInst,(char*) method_name);
if(method == NULL) {
- // FIXME: make this silent
//std::cerr << "Can't find '" << method_name << "' method" << std::endl;
Py_XDECREF(arglist);
+ if (res) {
+ Py_INCREF(Py_None);
+ *res = Py_None;
+ }
return false;
}
- PyObject *result = PyObject_CallObject(method, arglist);
+ PyObject *result = PyObject_CallObject(method, arglist);
Py_XDECREF(arglist);
if(result == NULL) {
@@ -44,6 +47,7 @@ bool PyCallbackObj::RunSimpleCallback(const char* method_name,
std::cerr << "Error in function " << method_name << std::endl;
PyErr_Print();
PyErr_Clear();
+
return false;
}
if(res != NULL)
@@ -113,6 +117,7 @@ void PyOpProgress::Done()
bool PyFetchProgress::MediaChange(string Media, string Drive)
{
+ PyCbObj_END_ALLOW_THREADS
//std::cout << "MediaChange" << std::endl;
PyObject *arglist = Py_BuildValue("(ss)", Media.c_str(), Drive.c_str());
PyObject *result;
@@ -126,6 +131,7 @@ bool PyFetchProgress::MediaChange(string Media, string Drive)
// FIXME: find out what it should return usually
//std::cerr << "res is: " << res << std::endl;
+ PyCbObj_BEGIN_ALLOW_THREADS
return res;
}
@@ -136,6 +142,7 @@ void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
// Added object file size and object partial size to
// parameters that are passed to updateStatus.
// -- Stephan
+ PyCbObj_END_ALLOW_THREADS
PyObject *arglist = Py_BuildValue("(sssikk)", Itm.URI.c_str(),
Itm.Description.c_str(),
Itm.ShortDesc.c_str(),
@@ -146,12 +153,13 @@ void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
RunSimpleCallback("update_status_full", arglist);
// legacy version of the interface
- arglist = Py_BuildValue("(sssi)", Itm.URI.c_str(),
- Itm.Description.c_str(),
- Itm.ShortDesc.c_str(),
- status);
+
+ arglist = Py_BuildValue("(sssi)", Itm.URI.c_str(), Itm.Description.c_str(),
+ Itm.ShortDesc.c_str(), status);
+
if(!RunSimpleCallback("update_status", arglist))
RunSimpleCallback("updateStatus", arglist);
+ PyCbObj_BEGIN_ALLOW_THREADS
}
void PyFetchProgress::IMSHit(pkgAcquire::ItemDesc &Itm)
@@ -206,6 +214,7 @@ void PyFetchProgress::Start()
//std::cout << "Start" << std::endl;
pkgAcquireStatus::Start();
+
if (PyObject_TypeCheck(callbackInst,&PyAcquireProgress_Type))
goto end;
@@ -214,30 +223,42 @@ void PyFetchProgress::Start()
// -- Stephan
PyObject *o;
- o = Py_BuildValue("d", 0.0f);
+ o = Py_BuildValue("d", 0);
PyObject_SetAttrString(callbackInst, "currentCPS", o);
Py_XDECREF(o);
- o = Py_BuildValue("d", 0.0f);
+
+ o = Py_BuildValue("d", 0);
PyObject_SetAttrString(callbackInst, "currentBytes", o);
Py_XDECREF(o);
+
o = Py_BuildValue("k", 0);
PyObject_SetAttrString(callbackInst, "currentItems", o);
Py_XDECREF(o);
o = Py_BuildValue("k", 0);
-
PyObject_SetAttrString(callbackInst, "totalItems", o);
Py_XDECREF(o);
- o = Py_BuildValue("d", 0.0f);
+
+ o = Py_BuildValue("d", 0);
PyObject_SetAttrString(callbackInst, "totalBytes", o);
Py_XDECREF(o);
end:
RunSimpleCallback("start");
+ /* After calling the start method we can safely allow
+ * other Python threads to do their work for now.
+ */
+ PyCbObj_BEGIN_ALLOW_THREADS
}
void PyFetchProgress::Stop()
{
+ /* After the stop operation occured no other threads
+ * are allowed. This is done so we have a matching
+ * PyCbObj_END_ALLOW_THREADS to our previous
+ * PyCbObj_BEGIN_ALLOW_THREADS (Python requires this!).
+ */
+ PyCbObj_END_ALLOW_THREADS
//std::cout << "Stop" << std::endl;
pkgAcquireStatus::Stop();
RunSimpleCallback("stop");
@@ -245,6 +266,7 @@ void PyFetchProgress::Stop()
bool PyFetchProgress::Pulse(pkgAcquire * Owner)
{
+ PyCbObj_END_ALLOW_THREADS
pkgAcquireStatus::Pulse(Owner);
//std::cout << "Pulse" << std::endl;
@@ -311,6 +333,7 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
}
return true;
}
+
// Go through the list of items and add active items to the
// activeItems vector.
map<pkgAcquire::Worker *, pkgAcquire::ItemDesc *> activeItemMap;
@@ -339,7 +362,7 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
int tuplePos;
for(tuplePos = 0, iter = activeItemMap.begin();
- iter != activeItemMap.end(); ++iter, tuplePos++) {
+ iter != activeItemMap.end(); ++iter, tuplePos++) {
pkgAcquire::Worker *worker = iter->first;
pkgAcquire::ItemDesc *itm = iter->second;
@@ -371,15 +394,19 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
PyObject *result;
bool res = true;
+
if (RunSimpleCallback("pulse_items", arglist, &result)) {
if (result != NULL && PyArg_Parse(result, "b", &res) && res == false) {
// the user returned a explicit false here, stop
+ PyCbObj_BEGIN_ALLOW_THREADS
return false;
}
}
+
arglist = Py_BuildValue("()");
if (!RunSimpleCallback("pulse", arglist, &result)) {
+ PyCbObj_BEGIN_ALLOW_THREADS
return true;
}
@@ -388,9 +415,11 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
// most of the time the user who subclasses the pulse()
// method forgot to add a return {True,False} so we just
// assume he wants a True
+ PyCbObj_BEGIN_ALLOW_THREADS
return true;
}
+ PyCbObj_BEGIN_ALLOW_THREADS
// fetching can be canceld by returning false
return res;
}
@@ -403,16 +432,20 @@ void PyInstallProgress::StartUpdate()
{
if (!RunSimpleCallback("start_update"))
RunSimpleCallback("startUpdate");
+ PyCbObj_BEGIN_ALLOW_THREADS
}
void PyInstallProgress::UpdateInterface()
{
+ PyCbObj_END_ALLOW_THREADS
if (!RunSimpleCallback("update_interface"))
RunSimpleCallback("updateInterface");
+ PyCbObj_BEGIN_ALLOW_THREADS
}
void PyInstallProgress::FinishUpdate()
{
+ PyCbObj_END_ALLOW_THREADS
if (!RunSimpleCallback("finish_update"))
RunSimpleCallback("finishUpdate");
}
@@ -471,9 +504,10 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
_exit(res);
}
-
StartUpdate();
+
+ PyCbObj_END_ALLOW_THREADS
if(PyObject_HasAttrString(callbackInst, "waitChild") ||
PyObject_HasAttrString(callbackInst, "wait_child")) {
PyObject *method;
@@ -492,14 +526,19 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
}
if(!PyArg_Parse(result, "i", &res) ) {
std::cerr << "custom waitChild() result could not be parsed?"<< std::endl;
+ PyCbObj_BEGIN_ALLOW_THREADS
return pkgPackageManager::Failed;
}
+ PyCbObj_BEGIN_ALLOW_THREADS
//std::cerr << "got child_res: " << res << std::endl;
} else {
//std::cerr << "using build-in waitpid()" << std::endl;
-
- while (waitpid(child_id, &ret, WNOHANG) == 0)
+ PyCbObj_BEGIN_ALLOW_THREADS
+ while (waitpid(child_id, &ret, WNOHANG) == 0) {
+ PyCbObj_END_ALLOW_THREADS
UpdateInterface();
+ PyCbObj_BEGIN_ALLOW_THREADS
+ }
res = (pkgPackageManager::OrderResult) WEXITSTATUS(ret);
//std::cerr << "build-in waitpid() got: " << res << std::endl;
diff --git a/python/progress.h b/python/progress.h
index 88bd3552..88c0a21b 100644
--- a/python/progress.h
+++ b/python/progress.h
@@ -15,6 +15,22 @@
#include <apt-pkg/cdrom.h>
#include <Python.h>
+/* PyCbObj_BEGIN_ALLOW_THREADS and PyCbObj_END_ALLOW_THREADS are sligthly
+ * modified versions of Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS.
+ * Instead of storing the thread state in a function-local variable these
+ * use a class attribute (with the same) name, allowing blocking and
+ * unblocking from different class methods.
+ * Py_BLOCK_THREADS and Py_UNBLOCK_THREADS do not define their own
+ * local variable but use the one provided by PyCbObj_BEGIN_ALLOW_THREADS
+ * and thus are the same as Py_BLOCK_THREADS and Py_UNBLOCK_THREADS.
+ */
+#define PyCbObj_BEGIN_ALLOW_THREADS \
+ _save = PyEval_SaveThread();
+#define PyCbObj_END_ALLOW_THREADS \
+ PyEval_RestoreThread(_save); \
+ _save = NULL;
+#define PyCbObj_BLOCK_THREADS Py_BLOCK_THREADS
+#define PyCbObj_UNBLOCK_THREADS Py_UNBLOCK_THREADS
typedef struct {
PyObject_HEAD
@@ -50,6 +66,7 @@ typedef struct {
class PyCallbackObj {
protected:
PyObject *callbackInst;
+ PyThreadState *_save;
public:
void setCallbackInst(PyObject *o) {