diff options
| -rw-r--r-- | apt/cache.py | 24 | ||||
| -rw-r--r-- | aptsources/distro.py | 4 | ||||
| -rw-r--r-- | debian/changelog | 40 | ||||
| -rw-r--r-- | python/progress.cc | 67 | ||||
| -rw-r--r-- | python/progress.h | 17 |
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) { |
