diff options
author | Klaus Kämpf <kkaempf@suse.de> | 2011-08-12 16:57:13 +0200 |
---|---|---|
committer | Klaus Kämpf <kkaempf@suse.de> | 2011-08-12 16:57:13 +0200 |
commit | f37ab25474c8ae5dea487255c1e29489647041fa (patch) | |
tree | 9ffc4383aa9a2e0eb9f818911c1ed06766600036 | |
parent | 7b79d70684bd777d21d1b7a058bec42eb052f825 (diff) | |
download | libzypp-bindings-f37ab25474c8ae5dea487255c1e29489647041fa.tar.gz libzypp-bindings-f37ab25474c8ae5dea487255c1e29489647041fa.tar.bz2 libzypp-bindings-f37ab25474c8ae5dea487255c1e29489647041fa.zip |
Further extend callbacks to cover ResolvableRemove
Still incomplete due to missing type conversion for
target::rpm::RemoveResolvableReport::Error
-rw-r--r-- | swig/Callbacks.i | 318 | ||||
-rw-r--r-- | swig/CommitCallbacks.h | 12 | ||||
-rw-r--r-- | swig/python/tests/commit_callbacks.py | 94 | ||||
-rw-r--r-- | swig/ruby/tests/commit_callbacks.rb | 17 |
4 files changed, 397 insertions, 44 deletions
diff --git a/swig/Callbacks.i b/swig/Callbacks.i index d4186aa..0aecb20 100644 --- a/swig/Callbacks.i +++ b/swig/Callbacks.i @@ -15,13 +15,201 @@ %{ #include <cstdarg> +#include <zypp/ZYppCallbacks.h> +/* + * Helpers + * + */ + +/* + * Action + * Symbol representation of :abort, :retry, and :ignore + * + */ + +static Target_Type action_abort() + { +#if defined(SWIGRUBY) + static VALUE value = Qnil; + if (value == Qnil) + value = ID2SYM(rb_intern("abort")); + return value; +#endif + } +static Target_Type action_retry() + { +#if defined(SWIGRUBY) + static VALUE value = Qnil; + if (value == Qnil) + value = ID2SYM(rb_intern("retry")); + return value; +#endif + } + +static Target_Type action_ignore() + { +#if defined(SWIGRUBY) + static VALUE value = Qnil; + if (value == Qnil) + value = ID2SYM(rb_intern("ignore")); + return value; +#endif + } + +/* + * Error + * Symbol representation of :no_error, :not_found, :io, :invalid + * + */ + +static Target_Type error_no_error() + { +#if defined(SWIGRUBY) + static VALUE value = Qnil; + if (value == Qnil) + value = ID2SYM(rb_intern("no_error")); + return value; +#endif +#if defined(SWIGPYTHON) + return Target_String("no_error"); +#endif + } + +static Target_Type error_not_found() + { +#if defined(SWIGRUBY) + static VALUE value = Qnil; + if (value == Qnil) + value = ID2SYM(rb_intern("not_found")); + return value; +#endif +#if defined(SWIGPYTHON) + return Target_String("not_found"); +#endif + } + +static Target_Type error_io() + { +#if defined(SWIGRUBY) + static VALUE value = Qnil; + if (value == Qnil) + value = ID2SYM(rb_intern("io")); + return value; +#endif +#if defined(SWIGPYTHON) + return Target_String("io"); +#endif + } + +static Target_Type error_invalid() + { +#if defined(SWIGRUBY) + static VALUE value = Qnil; + if (value == Qnil) + value = ID2SYM(rb_intern("invalid")); + return value; +#endif +#if defined(SWIGPYTHON) + return Target_String("invalid"); +#endif + } + +/* + * This is what makes people hate the ZYPP API. Why can't there + * be _one_ Error type ?! + */ +static Target_Type +remove_error2target(target::rpm::RemoveResolvableReport::Error error) +{ + Target_Type e; + switch(error) { + case target::rpm::RemoveResolvableReport::NO_ERROR: e = error_no_error(); break; + case target::rpm::RemoveResolvableReport::NOT_FOUND: e = error_not_found(); break; + case target::rpm::RemoveResolvableReport::IO: e = error_io(); break; + case target::rpm::RemoveResolvableReport::INVALID: e = error_invalid(); break; + } + return e; +} + + +/* + * This is what makes people hate the ZYPP API. Why can't there + * be _one_ Action type ?! + */ +static target::PatchScriptReport::Action +target2patch_script_action(Target_Type a) +{ +#if defined(SWIGPYTHON) + const char *s; + if (!PyString_Check(a)) { + SWIG_exception_fail(SWIG_TypeError, "Expected string type"); + } + s = PyString_AsString(a); + if (!strcmp(s, "abort")) + return zypp::target::PatchScriptReport::ABORT; + else if (!strcmp(s, "retry")) + return zypp::target::PatchScriptReport::RETRY; + else if (!strcmp(s, "ignore")) + return zypp::target::PatchScriptReport::IGNORE; + SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected \"abort\", \"retry\" or \"ignore\""); +#endif +#if defined(SWIGRUBY) + if (a == action_abort_sym()) + return zypp::target::PatchScriptReport::ABORT; + else if (a == action_retry_sym()) + return zypp::target::PatchScriptReport::RETRY; + else if (a == action_ignore_sym()) + return zypp::target::PatchScriptReport::IGNORE; + SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected :abort, :retry or :ignore"); +#endif +fail: + return zypp::target::PatchScriptReport::ABORT; +} + + +static target::rpm::RemoveResolvableReport::Action +target2removal_action(Target_Type a) +{ +#if defined(SWIGPYTHON) + const char *s; + if (!PyString_Check(a)) { + SWIG_exception_fail(SWIG_TypeError, "Expected string type"); + } + s = PyString_AsString(a); + if (!strcmp(s, "abort")) + return zypp::target::rpm::RemoveResolvableReport::ABORT; + else if (!strcmp(s, "retry")) + return zypp::target::rpm::RemoveResolvableReport::RETRY; + else if (!strcmp(s, "ignore")) + return zypp::target::rpm::RemoveResolvableReport::IGNORE; + SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected \"abort\", \"retry\" or \"ignore\""); +#endif +#if defined(SWIGRUBY) + if (a == action_abort_sym()) + return zypp::target::rpm::RemoveResolvableReport::ABORT; + else if (a == action_retry_sym()) + return zypp::target::rpm::RemoveResolvableReport::RETRY; + else if (a == action_ignore_sym()) + return zypp::target::rpm::RemoveResolvableReport::IGNORE; + SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected :abort, :retry or :ignore"); +#endif +fail: + return zypp::target::rpm::RemoveResolvableReport::ABORT; +} + + +/* + * target_call + * + * Generic helper to call a function of the target language + * + */ static Target_Type target_call(Target_Type instance, const char *name, int argc, ... ) { va_list ap; va_start(ap, argc); - printf("Calling %p->%s with %d args\n", (void *)instance, name, argc); #if defined(SWIGPYTHON) /* * Python call with multiple args is like Array @@ -44,21 +232,20 @@ target_call(Target_Type instance, const char *name, int argc, ... ) if (pyfunc == NULL) { - printf("%s not defined\n", name); PyErr_Print(); PyErr_Clear(); goto cleanup; } if (! PyCallable_Check(pyfunc)) { - printf("%s not callable\n", name); + fprintf(stderr,"%s not callable\n", name); goto cleanup; } result = PyObject_CallObject(pyfunc, argv); if (PyErr_Occurred()) { - printf("%s returned error\n", name); + fprintf(stderr,"%s returned error\n", name); PyErr_Print(); PyErr_Clear(); goto cleanup; @@ -87,9 +274,11 @@ cleanup: return result; } + /* * Patch message * + * calls 'show_message(zypp::Patch)' */ struct PatchMessageReportReceiver : public zypp::callback::ReceiveReport<zypp::target::PatchMessageReport> @@ -102,7 +291,17 @@ struct PatchMessageReportReceiver : public zypp::callback::ReceiveReport<zypp::t */ virtual bool show( zypp::Patch::constPtr & patch ) { - return true; + int result; + Target_Type r = SWIG_NewPointerObj((void *)&patch, SWIGTYPE_p_zypp__Patch, 0); + Target_Type res = target_call(instance, "patch_message", 1, r ); +#if defined(SWIGPYTHON) + result = PyObject_IsTrue(res) ? true : false; + if (res) Py_DecRef(res); +#endif +#if defined(SWIGRUBY) + result = RTEST(res) ? true : false; +#endif + return result; } }; @@ -120,27 +319,81 @@ struct PatchScriptReportReceiver : public zypp::callback::ReceiveReport<zypp::ta virtual void start( const zypp::Package::constPtr & package, const zypp::Pathname & path_r ) // script path { + Target_Type pac = SWIG_NewPointerObj((void *)&(*package), SWIGTYPE_p_zypp__Package, 0); + Target_Type path = SWIG_NewPointerObj((void *)&path_r, SWIGTYPE_p_zypp__filesystem__Pathname, 0); + Target_Type result = target_call(instance, "patch_script_start", 2, pac, path ); +#if defined(SWIGPYTHON) + if (result) Py_DecRef(result); + Py_DecRef(path); + Py_DecRef(pac); +#endif + return; } /** - * Progress provides the script output. If the script is quiet, + * Progress provides the script output (Notify=OUTPUT). If the script is quiet, * from time to time still-alive pings are sent to the ui. (Notify=PING) * Returning \c FALSE aborts script execution. */ virtual bool progress( Notify kind, const std::string &output ) { - return true; + int result; + Target_Type str = Target_String(output.c_str()); + Target_Type k; + switch(kind) { + case OUTPUT: +#if defined(SWIGPYTHON) + k = Target_String("OUTPUT"); +#endif +#if defined(SWIGRUBY) + k = ID2SYM(rb_intern("OUTPUT")); +#endif + break; + case PING: +#if defined(SWIGPYTHON) + k = Target_String("PING"); +#endif +#if defined(SWIGRUBY) + k = ID2SYM(rb_intern("PING")); +#endif + break; + } + Target_Type res = target_call(instance, "patch_script_progress", 2, k, str ); +#if defined(SWIGPYTHON) + result = PyObject_IsTrue(res) ? true : false; + if (res) Py_DecRef(res); + Py_DecRef(k); + Py_DecRef(str); +#endif +#if defined(SWIGRUBY) + result = RTEST(res) ? true : false; +#endif + return result; } - /** Report error. */ + /** Report patch script error. + */ virtual Action problem( const std::string & description ) { - return zypp::target::PatchScriptReport::ABORT; + Action result; + Target_Type str = Target_String(description.c_str()); + Target_Type res = target_call(instance, "patch_script_problem", 1, str ); + result = target2patch_script_action(res); +#if defined(SWIGPYTHON) + Py_DecRef(str); + if (res) Py_DecRef(res); +#endif + return result; } - /** Report success. */ + /** Patch script finish. */ virtual void finish() { + Target_Type res = target_call(instance, "patch_script_finish", 0 ); +#if defined(SWIGPYTHON) + if (res) Py_DecRef(res); +#endif + return; } }; @@ -155,12 +408,12 @@ struct RemoveResolvableReportReceiver : public zypp::callback::ReceiveReport<zyp Target_Type instance; -/* virtual void start( const zypp::Resolvable *resolvable ) */ virtual void start( Resolvable::constPtr resolvable ) { Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0); Target_Type result = target_call(instance, "removal_start", 1, r ); #if defined(SWIGPYTHON) + Py_DecRef(r); if (result) Py_DecRef(result); #endif return; @@ -168,16 +421,52 @@ struct RemoveResolvableReportReceiver : public zypp::callback::ReceiveReport<zyp virtual bool progress(int value, zypp::Resolvable::constPtr resolvable) { - return true; + bool result; + Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0); + Target_Type v = Target_Int(value); + Target_Type res = target_call(instance, "removal_progress", 2, r, v ); +#if defined(SWIGPYTHON) + result = PyObject_IsTrue(res) ? true : false; + Py_DecRef(v); + Py_DecRef(r); + if (res) Py_DecRef(res); +#endif +#if defined(SWIGRUBY) + result = RTEST(res) ? true : false; +#endif + return result; } - virtual Action problem( zypp::Resolvable::constPtr resolvable, Error error, const std::string & description ) + virtual Action problem( zypp::Resolvable::constPtr resolvable, target::rpm::RemoveResolvableReport::Error error, const std::string & description ) { - return RemoveResolvableReportReceiver::ABORT; + Action result; + Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0); + Target_Type e = remove_error2target(error); + Target_Type d = Target_String(description.c_str()); + Target_Type res = target_call(instance, "removal_problem", 3, r, e, d ); + result = target2removal_action(res); +#if defined(SWIGPYTHON) + if (res) Py_DecRef(res); + Py_DecRef(d); + Py_DecRef(e); + Py_DecRef(r); +#endif + return result; } virtual void finish( zypp::Resolvable::constPtr resolvable, Error error, const std::string & reason ) { + Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0); + Target_Type e = remove_error2target(error); + Target_Type d = Target_String(reason.c_str()); + Target_Type res = target_call(instance, "removal_finish", 3, r, e, d ); +#if defined(SWIGPYTHON) + if (res) Py_DecRef(res); + Py_DecRef(d); + Py_DecRef(e); + Py_DecRef(r); +#endif + return; } }; @@ -220,3 +509,4 @@ struct InstallResolvableReportReceiver : public zypp::callback::ReceiveReport<zy %} %include "CommitCallbacks.h" + diff --git a/swig/CommitCallbacks.h b/swig/CommitCallbacks.h index 2dd6f38..ca7446a 100644 --- a/swig/CommitCallbacks.h +++ b/swig/CommitCallbacks.h @@ -165,11 +165,11 @@ class CommitCallbacksEmitter { _patch_script->start(package, path_r); } - /** - * * Progress provides the script output. If the script is quiet, - * * from time to time still-alive pings are sent to the ui. (Notify=PING) - * * Returning \c FALSE aborts script execution. - * */ + /** + * Progress provides the script output. If the script is quiet, + * from time to time still-alive pings are sent to the ui. (Notify=PING) + * Returning \c FALSE aborts script execution. + */ bool script_progress( target::PatchScriptReport::Notify kind, const std::string &output ) { return _patch_script->progress(kind, output); @@ -188,3 +188,5 @@ class CommitCallbacksEmitter { } }; + +#define REMOVE_NO_ERROR target::rpm::RemoveResolvableReport::NO_ERROR diff --git a/swig/python/tests/commit_callbacks.py b/swig/python/tests/commit_callbacks.py index 32852f7..b7cc7d4 100644 --- a/swig/python/tests/commit_callbacks.py +++ b/swig/python/tests/commit_callbacks.py @@ -41,6 +41,21 @@ removals = 0 # # TODO: provide a complete list of function names and parameters # +# I. Patch message +# patch_message(zypp::Patch) - show patch message +# +# II. Patch script +# patch_script_start(zypp::Package, String) +# patch_script_progress(zypp::Notify, String) +# patch_script_problem(String) +# patch_script_finish() +# +# III. Removal +# removal_start(zypp::Resolvable) - start of resolvable uninstall +# removal_progress(zypp::Resolvable, Integer) - progress in percent +# removal_problem(zypp::Resolvable, zypp::Error, String) - problem report +# removal_finish(zypp::Resolvable, zypp::Error, String) - uninstall finish +# class CommitReceiver: # @@ -53,75 +68,104 @@ class CommitReceiver: removals += 1 print "Starting to remove ", resolvable + # + # removal_progress() is called during a resolvable (typically package) uninstall + # and be passed the resolvable to-be-removed and a percentage value + # + def removal_progress(self, resolvable, percentage): + assert percentage == 42 + print "Remove of ", resolvable, " at ", percentage, "%" + # # Testcase for Callbacks # class CommitCallbacksTestCase(unittest.TestCase): - # this will test the remove callback - def testRemoveCallback(self): + def setUp(self): # # Normal zypp startup # - Z = zypp.ZYppFactory_instance().getZYpp() - Z.initializeTarget( zypp.Pathname("/") ) - Z.target().load(); + self.Z = zypp.ZYppFactory_instance().getZYpp() + self.Z.initializeTarget( zypp.Pathname("/") ) + self.Z.target().load() # The 'zypp.CommitCallbacksEmitter()' is a test/debug class # which can be used to trigger various callbacks # (This is callback test code - we cannot do an actual package uninstall here!) - commit_callbacks_emitter = zypp.CommitCallbacksEmitter() + self.commit_callbacks_emitter = zypp.CommitCallbacksEmitter() # # create an instance of our CommitReceiver class defined above # - commit_receiver = CommitReceiver() + self.commit_receiver = CommitReceiver() # zypp.CommitCallbacks is the callback 'handler' which must be informed # about the receiver - commit_callbacks = zypp.CommitCallbacks() + self.commit_callbacks = zypp.CommitCallbacks() # # Ensure that no other receiver is registered # - assert None == commit_callbacks.receiver() + assert None == self.commit_callbacks.receiver() # # Connect the receiver instance with the callback handler # - commit_callbacks.connect(commit_receiver) + self.commit_callbacks.connect(self.commit_receiver) # # Ensure that its set correctly # - assert commit_receiver == commit_callbacks.receiver() + assert self.commit_receiver == self.commit_callbacks.receiver() + + def tearDown(self): + # + # Disconnect the receiver from the callback handler + # + self.commit_callbacks.disconnect() + + # + # Ensure that the disconnect was successful + # + assert None == self.commit_callbacks.receiver() + + # test patch message + def testPatchMessageCallback(self): + # + # Ugh, this would need a patch with a message :-/ + # + # FIXME + assert True + + # test patch script + def testPatchScriptCallback(self): + # + # Ugh, this would need a patch with a script :-/ + # + # FIXME + assert True + + # this will test the remove callback + def testRemoveCallback(self): # # Loop over pool - just to get real instances of Resolvable # - for item in Z.pool(): + for item in self.Z.pool(): print "Emitting removal of ", item.resolvable() # # Use the zypp.CommitCallbacksEmitter to fake an actual package removal # - commit_callbacks_emitter.remove_start(item.resolvable()) - print "Done" + resolvable = item.resolvable() + self.commit_callbacks_emitter.remove_start(resolvable) + self.commit_callbacks_emitter.remove_progress(resolvable, 42) +# self.commit_callbacks_emitter.remove_problem(resolvable, zypp.REMOVE_NO_ERROR, "All fine") +# self.commit_callbacks_emitter.remove_finish(resolvable, zypp.REMOVE_NO_ERROR, "Done") break # one is sufficient - # # Did the actual callback got executed ? # assert removals == 1 - # - # Disconnect the receiver from the callback handler - # - commit_callbacks.disconnect() - - # - # Ensure that the disconnect was successful - # - assert None == commit_callbacks.receiver() - if __name__ == '__main__': unittest.main() diff --git a/swig/ruby/tests/commit_callbacks.rb b/swig/ruby/tests/commit_callbacks.rb index 1dbd408..74767ce 100644 --- a/swig/ruby/tests/commit_callbacks.rb +++ b/swig/ruby/tests/commit_callbacks.rb @@ -23,6 +23,23 @@ class CommitCallbacksTest < Test::Unit::TestCase # In Ruby the class is also an object, so we connect to the class commit_callbacks.connect CommitReceiver assert_equal CommitReceiver, commit_callbacks.receiver + + z = Zypp::ZYppFactory::instance.getZYpp + + z.initializeTarget(Zypp::Pathname.new("/")) + t = z.target + t.load + t.buildCache + + emitter = Zypp::CommitCallbacksEmitter.new + p = z.pool + p.each do |item| + puts "Emitting removal of ", item + puts item.methods.inspect + emitter.remove_start(item) + break + end + commit_callbacks.disconnect assert_equal nil, commit_callbacks.receiver end |