summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Kämpf <kkaempf@suse.de>2011-08-12 16:57:13 +0200
committerKlaus Kämpf <kkaempf@suse.de>2011-08-12 16:57:13 +0200
commitf37ab25474c8ae5dea487255c1e29489647041fa (patch)
tree9ffc4383aa9a2e0eb9f818911c1ed06766600036
parent7b79d70684bd777d21d1b7a058bec42eb052f825 (diff)
downloadlibzypp-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.i318
-rw-r--r--swig/CommitCallbacks.h12
-rw-r--r--swig/python/tests/commit_callbacks.py94
-rw-r--r--swig/ruby/tests/commit_callbacks.rb17
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